summaryrefslogtreecommitdiff
path: root/boost/interprocess
diff options
context:
space:
mode:
Diffstat (limited to 'boost/interprocess')
-rw-r--r--boost/interprocess/allocators/adaptive_pool.hpp46
-rw-r--r--boost/interprocess/allocators/allocator.hpp51
-rw-r--r--boost/interprocess/allocators/cached_adaptive_pool.hpp26
-rw-r--r--boost/interprocess/allocators/cached_node_allocator.hpp24
-rw-r--r--boost/interprocess/allocators/detail/adaptive_node_pool.hpp16
-rw-r--r--boost/interprocess/allocators/detail/allocator_common.hpp121
-rw-r--r--boost/interprocess/allocators/detail/node_pool.hpp12
-rw-r--r--boost/interprocess/allocators/detail/node_tools.hpp4
-rw-r--r--boost/interprocess/allocators/node_allocator.hpp48
-rw-r--r--boost/interprocess/allocators/private_adaptive_pool.hpp42
-rw-r--r--boost/interprocess/allocators/private_node_allocator.hpp42
-rw-r--r--boost/interprocess/anonymous_shared_memory.hpp14
-rw-r--r--boost/interprocess/containers/allocation_type.hpp8
-rw-r--r--boost/interprocess/containers/containers_fwd.hpp8
-rw-r--r--boost/interprocess/containers/deque.hpp4
-rw-r--r--boost/interprocess/containers/flat_map.hpp4
-rw-r--r--boost/interprocess/containers/flat_set.hpp4
-rw-r--r--boost/interprocess/containers/list.hpp4
-rw-r--r--boost/interprocess/containers/map.hpp4
-rw-r--r--boost/interprocess/containers/pair.hpp4
-rw-r--r--boost/interprocess/containers/set.hpp4
-rw-r--r--boost/interprocess/containers/slist.hpp4
-rw-r--r--boost/interprocess/containers/stable_vector.hpp4
-rw-r--r--boost/interprocess/containers/string.hpp4
-rw-r--r--boost/interprocess/containers/vector.hpp4
-rw-r--r--boost/interprocess/containers/version_type.hpp4
-rw-r--r--boost/interprocess/creation_tags.hpp6
-rw-r--r--boost/interprocess/detail/atomic.hpp241
-rw-r--r--boost/interprocess/detail/cast_tags.hpp6
-rw-r--r--boost/interprocess/detail/config_begin.hpp6
-rw-r--r--boost/interprocess/detail/config_end.hpp6
-rw-r--r--boost/interprocess/detail/config_external_begin.hpp18
-rw-r--r--boost/interprocess/detail/config_external_end.hpp12
-rw-r--r--boost/interprocess/detail/file_locking_helpers.hpp6
-rw-r--r--boost/interprocess/detail/file_wrapper.hpp25
-rw-r--r--boost/interprocess/detail/in_place_interface.hpp6
-rw-r--r--boost/interprocess/detail/intermodule_singleton.hpp9
-rw-r--r--boost/interprocess/detail/intermodule_singleton_common.hpp61
-rw-r--r--boost/interprocess/detail/interprocess_tester.hpp6
-rw-r--r--boost/interprocess/detail/intersegment_ptr.hpp48
-rw-r--r--boost/interprocess/detail/managed_global_memory.hpp10
-rw-r--r--boost/interprocess/detail/managed_memory_impl.hpp102
-rw-r--r--boost/interprocess/detail/managed_multi_shared_memory.hpp42
-rw-r--r--boost/interprocess/detail/managed_open_or_create_impl.hpp65
-rw-r--r--boost/interprocess/detail/math_functions.hpp8
-rw-r--r--boost/interprocess/detail/min_max.hpp4
-rw-r--r--boost/interprocess/detail/move.hpp8
-rw-r--r--boost/interprocess/detail/mpl.hpp4
-rw-r--r--boost/interprocess/detail/multi_segment_services.hpp4
-rw-r--r--boost/interprocess/detail/named_proxy.hpp14
-rw-r--r--boost/interprocess/detail/os_file_functions.hpp146
-rw-r--r--boost/interprocess/detail/os_thread_functions.hpp417
-rw-r--r--boost/interprocess/detail/pointer_type.hpp4
-rw-r--r--boost/interprocess/detail/portable_intermodule_singleton.hpp25
-rw-r--r--boost/interprocess/detail/posix_time_types_wrk.hpp6
-rw-r--r--boost/interprocess/detail/preprocessor.hpp160
-rw-r--r--boost/interprocess/detail/ptime_wrk.hpp6
-rw-r--r--boost/interprocess/detail/robust_emulation.hpp96
-rw-r--r--boost/interprocess/detail/segment_manager_helper.hpp61
-rw-r--r--boost/interprocess/detail/shared_dir_helpers.hpp (renamed from boost/interprocess/detail/tmp_dir_helpers.hpp)112
-rw-r--r--boost/interprocess/detail/transform_iterator.hpp26
-rw-r--r--boost/interprocess/detail/type_traits.hpp17
-rw-r--r--boost/interprocess/detail/utilities.hpp72
-rw-r--r--boost/interprocess/detail/variadic_templates_tools.hpp4
-rw-r--r--boost/interprocess/detail/win32_api.hpp1587
-rw-r--r--boost/interprocess/detail/windows_intermodule_singleton.hpp28
-rw-r--r--boost/interprocess/detail/workaround.hpp97
-rw-r--r--boost/interprocess/detail/xsi_shared_memory_device.hpp28
-rw-r--r--boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp22
-rw-r--r--boost/interprocess/errors.hpp29
-rw-r--r--boost/interprocess/exceptions.hpp8
-rw-r--r--boost/interprocess/file_mapping.hpp34
-rw-r--r--boost/interprocess/indexes/flat_map_index.hpp14
-rw-r--r--boost/interprocess/indexes/iset_index.hpp26
-rw-r--r--boost/interprocess/indexes/iunordered_set_index.hpp34
-rw-r--r--boost/interprocess/indexes/map_index.hpp14
-rw-r--r--boost/interprocess/indexes/null_index.hpp14
-rw-r--r--boost/interprocess/indexes/unordered_map_index.hpp18
-rw-r--r--boost/interprocess/interprocess_fwd.hpp125
-rw-r--r--boost/interprocess/ipc/message_queue.hpp574
-rw-r--r--boost/interprocess/managed_external_buffer.hpp34
-rw-r--r--boost/interprocess/managed_heap_memory.hpp39
-rw-r--r--boost/interprocess/managed_mapped_file.hpp73
-rw-r--r--boost/interprocess/managed_shared_memory.hpp81
-rw-r--r--boost/interprocess/managed_windows_shared_memory.hpp66
-rw-r--r--boost/interprocess/managed_xsi_shared_memory.hpp63
-rw-r--r--boost/interprocess/mapped_region.hpp305
-rw-r--r--boost/interprocess/mem_algo/detail/mem_algo_common.hpp244
-rw-r--r--boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp6
-rw-r--r--boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp76
-rw-r--r--boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp76
-rw-r--r--boost/interprocess/mem_algo/rbtree_best_fit.hpp139
-rw-r--r--boost/interprocess/mem_algo/simple_seq_fit.hpp12
-rw-r--r--boost/interprocess/offset_ptr.hpp473
-rw-r--r--boost/interprocess/permissions.hpp20
-rw-r--r--boost/interprocess/segment_manager.hpp304
-rw-r--r--boost/interprocess/shared_memory_object.hpp74
-rw-r--r--boost/interprocess/smart_ptr/deleter.hpp4
-rw-r--r--boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp4
-rw-r--r--boost/interprocess/smart_ptr/detail/shared_count.hpp7
-rw-r--r--boost/interprocess/smart_ptr/detail/sp_counted_base.hpp6
-rw-r--r--boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp4
-rw-r--r--boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp15
-rw-r--r--boost/interprocess/smart_ptr/enable_shared_from_this.hpp14
-rw-r--r--boost/interprocess/smart_ptr/intrusive_ptr.hpp24
-rw-r--r--boost/interprocess/smart_ptr/scoped_ptr.hpp18
-rw-r--r--boost/interprocess/smart_ptr/shared_ptr.hpp40
-rw-r--r--boost/interprocess/smart_ptr/unique_ptr.hpp512
-rw-r--r--boost/interprocess/smart_ptr/weak_ptr.hpp22
-rw-r--r--boost/interprocess/streams/bufferstream.hpp183
-rw-r--r--boost/interprocess/streams/vectorstream.hpp155
-rw-r--r--boost/interprocess/sync/detail/common_algorithms.hpp77
-rw-r--r--boost/interprocess/sync/detail/condition_algorithm_8a.hpp127
-rw-r--r--boost/interprocess/sync/detail/condition_any_algorithm.hpp220
-rw-r--r--boost/interprocess/sync/detail/locks.hpp97
-rw-r--r--boost/interprocess/sync/file_lock.hpp102
-rw-r--r--boost/interprocess/sync/interprocess_condition.hpp74
-rw-r--r--boost/interprocess/sync/interprocess_condition_any.hpp133
-rw-r--r--boost/interprocess/sync/interprocess_mutex.hpp72
-rw-r--r--boost/interprocess/sync/interprocess_recursive_mutex.hpp16
-rw-r--r--boost/interprocess/sync/interprocess_semaphore.hpp16
-rw-r--r--boost/interprocess/sync/interprocess_sharable_mutex.hpp345
-rw-r--r--boost/interprocess/sync/interprocess_upgradable_mutex.hpp156
-rw-r--r--boost/interprocess/sync/lock_options.hpp8
-rw-r--r--boost/interprocess/sync/mutex_family.hpp4
-rw-r--r--boost/interprocess/sync/named_condition.hpp45
-rw-r--r--boost/interprocess/sync/named_condition_any.hpp151
-rw-r--r--boost/interprocess/sync/named_mutex.hpp45
-rw-r--r--boost/interprocess/sync/named_recursive_mutex.hpp28
-rw-r--r--boost/interprocess/sync/named_semaphore.hpp24
-rw-r--r--boost/interprocess/sync/named_sharable_mutex.hpp230
-rw-r--r--boost/interprocess/sync/named_upgradable_mutex.hpp61
-rw-r--r--boost/interprocess/sync/null_mutex.hpp12
-rw-r--r--boost/interprocess/sync/posix/condition.hpp25
-rw-r--r--boost/interprocess/sync/posix/mutex.hpp29
-rw-r--r--boost/interprocess/sync/posix/named_mutex.hpp24
-rw-r--r--boost/interprocess/sync/posix/named_semaphore.hpp8
-rw-r--r--boost/interprocess/sync/posix/pthread_helpers.hpp14
-rw-r--r--boost/interprocess/sync/posix/ptime_to_timespec.hpp10
-rw-r--r--boost/interprocess/sync/posix/recursive_mutex.hpp31
-rw-r--r--boost/interprocess/sync/posix/semaphore.hpp4
-rw-r--r--boost/interprocess/sync/posix/semaphore_wrapper.hpp70
-rw-r--r--boost/interprocess/sync/scoped_lock.hpp18
-rw-r--r--boost/interprocess/sync/sharable_lock.hpp22
-rw-r--r--boost/interprocess/sync/shm/named_condition.hpp235
-rw-r--r--boost/interprocess/sync/shm/named_condition_any.hpp191
-rw-r--r--boost/interprocess/sync/shm/named_creation_functor.hpp12
-rw-r--r--boost/interprocess/sync/shm/named_mutex.hpp45
-rw-r--r--boost/interprocess/sync/shm/named_recursive_mutex.hpp34
-rw-r--r--boost/interprocess/sync/shm/named_semaphore.hpp29
-rw-r--r--boost/interprocess/sync/shm/named_upgradable_mutex.hpp53
-rw-r--r--boost/interprocess/sync/spin/condition.hpp43
-rw-r--r--boost/interprocess/sync/spin/interprocess_barrier.hpp4
-rw-r--r--boost/interprocess/sync/spin/mutex.hpp43
-rw-r--r--boost/interprocess/sync/spin/recursive_mutex.hpp9
-rw-r--r--boost/interprocess/sync/spin/semaphore.hpp36
-rw-r--r--boost/interprocess/sync/spin/wait.hpp181
-rw-r--r--boost/interprocess/sync/upgradable_lock.hpp20
-rw-r--r--boost/interprocess/sync/windows/condition.hpp95
-rw-r--r--boost/interprocess/sync/windows/mutex.hpp8
-rw-r--r--boost/interprocess/sync/windows/named_condition.hpp306
-rw-r--r--boost/interprocess/sync/windows/named_condition_any.hpp240
-rw-r--r--boost/interprocess/sync/windows/named_mutex.hpp10
-rw-r--r--boost/interprocess/sync/windows/named_recursive_mutex.hpp6
-rw-r--r--boost/interprocess/sync/windows/named_semaphore.hpp10
-rw-r--r--boost/interprocess/sync/windows/named_sync.hpp20
-rw-r--r--boost/interprocess/sync/windows/recursive_mutex.hpp4
-rw-r--r--boost/interprocess/sync/windows/semaphore.hpp9
-rw-r--r--boost/interprocess/sync/windows/sync_utils.hpp32
-rw-r--r--boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp77
-rw-r--r--boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp66
-rw-r--r--boost/interprocess/sync/windows/winapi_wrapper_common.hpp93
-rw-r--r--boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp4
-rw-r--r--boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp6
-rw-r--r--boost/interprocess/sync/xsi/xsi_named_mutex.hpp26
-rw-r--r--boost/interprocess/windows_shared_memory.hpp40
-rw-r--r--boost/interprocess/xsi_key.hpp12
-rw-r--r--boost/interprocess/xsi_shared_memory.hpp24
178 files changed, 7869 insertions, 4576 deletions
diff --git a/boost/interprocess/allocators/adaptive_pool.hpp b/boost/interprocess/allocators/adaptive_pool.hpp
index a85202b4ee..d21fe1eda4 100644
--- a/boost/interprocess/allocators/adaptive_pool.hpp
+++ b/boost/interprocess/allocators/adaptive_pool.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP
#define BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -40,7 +40,7 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail{
@@ -66,7 +66,7 @@ class adaptive_pool_base
typedef adaptive_pool_base
<Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> self_t;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template <int dummy>
struct node_pool
@@ -77,7 +77,7 @@ class adaptive_pool_base
static type *get(void *p)
{ return static_cast<type*>(p); }
};
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
BOOST_STATIC_ASSERT((Version <=2));
@@ -105,18 +105,18 @@ class adaptive_pool_base
//!adaptive_pool_base
template<class T2>
struct rebind
- {
+ {
typedef adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
};
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
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
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor from a segment manager. If not present, constructs a node
@@ -129,8 +129,8 @@ class adaptive_pool_base
//!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();
+ {
+ node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count();
}
//!Assignment from other adaptive_pool_base
@@ -169,10 +169,10 @@ class adaptive_pool_base
friend void swap(self_t &alloc1, self_t &alloc2)
{ ipcdetail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
void_pointer mp_node_pool;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!Equality test for same type
@@ -211,7 +211,7 @@ class adaptive_pool_v1
template<class T2>
struct rebind
- {
+ {
typedef adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
};
@@ -228,7 +228,7 @@ class adaptive_pool_v1
} //namespace ipcdetail{
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!An STL node allocator that uses a segment manager as memory
//!source. The internal pointer type will of the same type (raw, smart) as
@@ -251,7 +251,7 @@ template < class T
, unsigned char OverheadPercent
>
class adaptive_pool
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
: public ipcdetail::adaptive_pool_base
< 2
, T
@@ -260,7 +260,7 @@ class adaptive_pool
, MaxFreeBlocks
, OverheadPercent
>
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
{
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -271,7 +271,7 @@ class adaptive_pool
template<class T2>
struct rebind
- {
+ {
typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
};
@@ -303,7 +303,7 @@ class adaptive_pool
//!adaptive_pool
template<class T2>
struct rebind
- {
+ {
typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
};
@@ -400,12 +400,12 @@ class adaptive_pool
//!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);
+ void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
- multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -413,7 +413,7 @@ class adaptive_pool
//!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);
+ void deallocate_many(multiallocation_chain &chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -426,7 +426,7 @@ class adaptive_pool
//!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);
+ void allocate_individual(size_type num_elements, multiallocation_chain &chain);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -439,7 +439,7 @@ class adaptive_pool
//!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);
+ void deallocate_individual(multiallocation_chain &chain);
#endif
};
diff --git a/boost/interprocess/allocators/allocator.hpp b/boost/interprocess/allocators/allocator.hpp
index 38e8c6901a..e3b5cc86c8 100644
--- a/boost/interprocess/allocators/allocator.hpp
+++ b/boost/interprocess/allocators/allocator.hpp
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_ALLOCATOR_HPP
#define BOOST_INTERPROCESS_ALLOCATOR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -57,7 +57,7 @@ class allocator
typedef SegmentManager segment_manager;
typedef typename SegmentManager::void_pointer void_pointer;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
//Self type
@@ -85,7 +85,7 @@ class allocator
//Pointer to the allocator
alloc_ptr_t mp_mngr;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
typedef T value_type;
@@ -104,18 +104,18 @@ class allocator
typedef boost::interprocess::version_type<allocator, 2> version;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Experimental. Don't use.
typedef boost::container::container_detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Obtains an allocator that allocates
//!objects of type T2
template<class T2>
struct rebind
- {
+ {
typedef allocator<T2, SegmentManager> other;
};
@@ -145,8 +145,9 @@ class allocator
pointer allocate(size_type count, cvoid_ptr hint = 0)
{
(void)hint;
- if(count > this->max_size())
+ if(size_overflows<sizeof(T)>(count)){
throw bad_alloc();
+ }
return pointer(static_cast<value_type*>(mp_mngr->allocate(count*sizeof(T))));
}
@@ -169,7 +170,7 @@ class allocator
//!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);
}
@@ -189,19 +190,20 @@ class allocator
//!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)
+ void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain)
{
- return multiallocation_chain(mp_mngr->allocate_many(sizeof(T)*elem_size, num_elements));
+ if(size_overflows<sizeof(T)>(elem_size)){
+ throw bad_alloc();
+ }
+ mp_mngr->allocate_many(elem_size*sizeof(T), num_elements, chain);
}
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
- multiallocation_chain allocate_many
- (const size_type *elem_sizes, size_type n_elements)
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
{
- multiallocation_chain(mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T)));
+ mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T), chain);
}
//!Allocates many elements of size elem_size in a contiguous block
@@ -210,10 +212,8 @@ class allocator
//!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());
- }
+ void deallocate_many(multiallocation_chain &chain)
+ { mp_mngr->deallocate_many(chain); }
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -227,9 +227,8 @@ class allocator
//!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); }
+ void allocate_individual(size_type num_elements, multiallocation_chain &chain)
+ { this->allocate_many(1, num_elements, chain); }
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -243,8 +242,8 @@ class allocator
//!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)); }
+ void deallocate_individual(multiallocation_chain &chain)
+ { this->deallocate_many(chain); }
//!Returns address of mutable object.
//!Never throws
@@ -286,7 +285,7 @@ bool operator!=(const allocator<T, SegmentManager> &alloc1,
} //namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template<class T>
struct has_trivial_destructor;
@@ -297,7 +296,7 @@ struct has_trivial_destructor
{
static const bool value = true;
};
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace boost {
diff --git a/boost/interprocess/allocators/cached_adaptive_pool.hpp b/boost/interprocess/allocators/cached_adaptive_pool.hpp
index 98af033fe6..7b1921b254 100644
--- a/boost/interprocess/allocators/cached_adaptive_pool.hpp
+++ b/boost/interprocess/allocators/cached_adaptive_pool.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP
#define BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -33,7 +33,7 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail {
@@ -69,7 +69,7 @@ class cached_adaptive_pool_v1
template<class T2>
struct rebind
- {
+ {
typedef cached_adaptive_pool_v1
<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
};
@@ -91,7 +91,7 @@ class cached_adaptive_pool_v1
} //namespace ipcdetail{
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!An STL node allocator that uses a segment manager as memory
//!source. The internal pointer type will of the same type (raw, smart) as
@@ -117,7 +117,7 @@ template < class T
, unsigned char OverheadPercent
>
class cached_adaptive_pool
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
: public ipcdetail::cached_allocator_impl
< T
, ipcdetail::shared_adaptive_node_pool
@@ -128,7 +128,7 @@ class cached_adaptive_pool
, OverheadPercent
>
, 2>
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
{
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -149,7 +149,7 @@ class cached_adaptive_pool
template<class T2>
struct rebind
- {
+ {
typedef cached_adaptive_pool
<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
};
@@ -183,7 +183,7 @@ class cached_adaptive_pool
//!cached_adaptive_pool
template<class T2>
struct rebind
- {
+ {
typedef cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
};
@@ -280,12 +280,12 @@ class cached_adaptive_pool
//!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);
+ void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
- multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -293,7 +293,7 @@ class cached_adaptive_pool
//!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);
+ void deallocate_many(multiallocation_chain &chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -319,7 +319,7 @@ class cached_adaptive_pool
//!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);
+ 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);
diff --git a/boost/interprocess/allocators/cached_node_allocator.hpp b/boost/interprocess/allocators/cached_node_allocator.hpp
index b0ad0e4ebc..5ac6aab2c0 100644
--- a/boost/interprocess/allocators/cached_node_allocator.hpp
+++ b/boost/interprocess/allocators/cached_node_allocator.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP
#define BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -34,7 +34,7 @@ namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail {
@@ -64,7 +64,7 @@ class cached_node_allocator_v1
template<class T2>
struct rebind
- {
+ {
typedef cached_node_allocator_v1
<T2, SegmentManager, NodesPerBlock> other;
};
@@ -86,14 +86,14 @@ class cached_node_allocator_v1
} //namespace ipcdetail{
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
template < class T
, class SegmentManager
, std::size_t NodesPerBlock
>
class cached_node_allocator
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
: public ipcdetail::cached_allocator_impl
< T
, ipcdetail::shared_node_pool
@@ -102,7 +102,7 @@ class cached_node_allocator
, NodesPerBlock
>
, 2>
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
{
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -122,7 +122,7 @@ class cached_node_allocator
template<class T2>
struct rebind
- {
+ {
typedef cached_node_allocator<T2, SegmentManager, NodesPerBlock> other;
};
@@ -155,7 +155,7 @@ class cached_node_allocator
//!cached_node_allocator
template<class T2>
struct rebind
- {
+ {
typedef cached_node_allocator<T2, SegmentManager> other;
};
@@ -252,12 +252,12 @@ class cached_node_allocator
//!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);
+ void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
- multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -265,7 +265,7 @@ class cached_node_allocator
//!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);
+ void deallocate_many(multiallocation_chain &chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
diff --git a/boost/interprocess/allocators/detail/adaptive_node_pool.hpp b/boost/interprocess/allocators/detail/adaptive_node_pool.hpp
index abe183146f..dd697902c4 100644
--- a/boost/interprocess/allocators/detail/adaptive_node_pool.hpp
+++ b/boost/interprocess/allocators/detail/adaptive_node_pool.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP
#define BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -45,10 +45,16 @@ template< class SegmentManager
>
class private_adaptive_node_pool
: public boost::container::container_detail::private_adaptive_node_pool_impl
- <typename SegmentManager::segment_manager_base_type>
+ < typename SegmentManager::segment_manager_base_type
+ , ::boost::container::adaptive_pool_flag::size_ordered |
+ ::boost::container::adaptive_pool_flag::address_ordered
+ >
{
typedef boost::container::container_detail::private_adaptive_node_pool_impl
- <typename SegmentManager::segment_manager_base_type> base_t;
+ < typename SegmentManager::segment_manager_base_type
+ , ::boost::container::adaptive_pool_flag::size_ordered |
+ ::boost::container::adaptive_pool_flag::address_ordered
+ > base_t;
//Non-copyable
private_adaptive_node_pool();
private_adaptive_node_pool(const private_adaptive_node_pool &);
@@ -74,7 +80,7 @@ class private_adaptive_node_pool
};
//!Pooled shared memory allocator using adaptive pool. Includes
-//!a reference count but the class does not delete itself, this is
+//!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
diff --git a/boost/interprocess/allocators/detail/allocator_common.hpp b/boost/interprocess/allocators/detail/allocator_common.hpp
index ba14d3f64d..eb8fbfc314 100644
--- a/boost/interprocess/allocators/detail/allocator_common.hpp
+++ b/boost/interprocess/allocators/detail/allocator_common.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
#define BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -26,7 +30,7 @@
#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/move/utility_core.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <algorithm> //std::swap
@@ -73,7 +77,7 @@ namespace ipcdetail {
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()()
@@ -90,7 +94,7 @@ struct get_or_create_node_pool_func
//!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;
};
@@ -118,7 +122,7 @@ struct destroy_if_last_link_func
//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
@@ -173,7 +177,7 @@ class cache_impl
~cache_impl()
{
this->deallocate_all_cached_nodes();
- ipcdetail::destroy_node_pool_if_last_link(ipcdetail::to_raw_pointer(mp_node_pool));
+ ipcdetail::destroy_node_pool_if_last_link(ipcdetail::to_raw_pointer(mp_node_pool));
}
NodePool *get_node_pool() const
@@ -189,34 +193,29 @@ class cache_impl
{
//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);
+ mp_node_pool->allocate_nodes(m_max_cached_nodes/2, m_cached_nodes);
}
- void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.front());
- m_cached_nodes.pop_front();
+ void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front());
return ret;
}
- multiallocation_chain cached_allocation(size_type n)
+ void cached_allocation(size_type n, multiallocation_chain &chain)
{
- 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();
+ void *ret = ipcdetail::to_raw_pointer(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);
+ mp_node_pool->allocate_nodes(n - allocated, chain);
}
- return boost::move(chain);
}
BOOST_CATCH(...){
- this->cached_deallocation(boost::move(chain));
+ this->cached_deallocation(chain);
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -235,7 +234,7 @@ class cache_impl
m_cached_nodes.push_front(ptr);
}
- void cached_deallocation(multiallocation_chain chain)
+ void cached_deallocation(multiallocation_chain &chain)
{
m_cached_nodes.splice_after(m_cached_nodes.before_begin(), chain);
@@ -262,7 +261,7 @@ class cache_impl
void deallocate_all_cached_nodes()
{
if(m_cached_nodes.empty()) return;
- mp_node_pool->deallocate_nodes(boost::move(m_cached_nodes));
+ mp_node_pool->deallocate_nodes(m_cached_nodes);
}
private:
@@ -290,7 +289,7 @@ class cache_impl
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));
+ mp_node_pool->deallocate_nodes(chain);
}
public:
@@ -335,7 +334,7 @@ class array_allocation_impl
//!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);
}
@@ -355,17 +354,20 @@ class array_allocation_impl
//!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)
+ void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain)
{
- return this->derived()->get_segment_manager()->allocate_many(sizeof(T)*elem_size, num_elements);
+ if(size_overflows<sizeof(T)>(elem_size)){
+ throw bad_alloc();
+ }
+ this->derived()->get_segment_manager()->allocate_many(elem_size*sizeof(T), num_elements, chain);
}
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
- multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements)
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
{
- return this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T));
+ this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T), chain);
}
//!Allocates many elements of size elem_size in a contiguous block
@@ -374,8 +376,8 @@ class array_allocation_impl
//!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)); }
+ void deallocate_many(multiallocation_chain &chain)
+ { this->derived()->get_segment_manager()->deallocate_many(chain); }
//!Returns the number of elements that could be
//!allocated. Never throws
@@ -457,14 +459,17 @@ class node_pool_allocation_impl
(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())
+ if(size_overflows<sizeof(T)>(count)){
throw bad_alloc();
- else if(Version == 1 && count == 1)
+ }
+ else if(Version == 1 && count == 1){
return pointer(static_cast<value_type*>
(pool->allocate_node()));
- else
+ }
+ else{
return pointer(static_cast<value_type*>
- (pool->get_segment_manager()->allocate(sizeof(T)*count)));
+ (pool->get_segment_manager()->allocate(count*sizeof(T))));
+ }
}
//!Deallocate allocated memory. Never throws
@@ -495,11 +500,11 @@ class node_pool_allocation_impl
//!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)
+ void allocate_individual(size_type num_elements, multiallocation_chain &chain)
{
typedef typename node_pool<0>::type node_pool_t;
node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
- return multiallocation_chain(pool->allocate_nodes(num_elements));
+ pool->allocate_nodes(num_elements, chain);
}
//!Deallocates memory previously allocated with allocate_one().
@@ -518,10 +523,10 @@ class node_pool_allocation_impl
//!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)
+ void deallocate_individual(multiallocation_chain &chain)
{
node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes
- (chain.extract_multiallocation_chain());
+ (chain);
}
//!Deallocates all free blocks of the pool
@@ -605,14 +610,15 @@ class cached_allocator_impl
{
(void)hint;
void * ret;
- if(count > this->max_size())
+ if(size_overflows<sizeof(T)>(count)){
throw bad_alloc();
+ }
else if(Version == 1 && count == 1){
ret = m_cache.cached_allocation();
}
else{
- ret = this->get_segment_manager()->allocate(sizeof(T)*count);
- }
+ ret = this->get_segment_manager()->allocate(count*sizeof(T));
+ }
return pointer(static_cast<T*>(ret));
}
@@ -640,8 +646,8 @@ class cached_allocator_impl
//!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)); }
+ void allocate_individual(size_type num_elements, multiallocation_chain &chain)
+ { this->m_cache.cached_allocation(num_elements, chain); }
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -655,12 +661,8 @@ class cached_allocator_impl
//!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));
- }
+ void deallocate_individual(multiallocation_chain &chain)
+ { m_cache.cached_deallocation(chain); }
//!Deallocates all free blocks of the pool
void deallocate_free_blocks()
@@ -678,9 +680,10 @@ class cached_allocator_impl
void deallocate_free_chunks()
{ m_cache.get_node_pool()->deallocate_free_blocks(); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
cache_impl<node_pool_t> m_cache;
+ #endif //!defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
};
//!Equality test for same type of
@@ -699,7 +702,7 @@ bool operator!=(const cached_allocator_impl<T, N, V> &alloc1,
//!Pooled shared memory allocator using adaptive pool. Includes
-//!a reference count but the class does not delete itself, this is
+//!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>
@@ -736,7 +739,7 @@ class shared_pool_impl
//-----------------------
return private_node_allocator_t::allocate_node();
}
-
+
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *ptr)
{
@@ -745,25 +748,15 @@ class shared_pool_impl
//-----------------------
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)
+ void allocate_nodes(const size_type n, multiallocation_chain &chain)
{
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//-----------------------
- return private_node_allocator_t::allocate_nodes(n);
+ private_node_allocator_t::allocate_nodes(n, chain);
}
//!Deallocates a linked list of nodes ending in null pointer. Never throws
@@ -776,12 +769,12 @@ class shared_pool_impl
}
//!Deallocates the nodes pointed by the multiallocation iterator. Never throws
- void deallocate_nodes(multiallocation_chain chain)
+ void deallocate_nodes(multiallocation_chain &chain)
{
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//-----------------------
- private_node_allocator_t::deallocate_nodes(boost::move(chain));
+ private_node_allocator_t::deallocate_nodes(chain);
}
//!Deallocates all the free blocks of memory. Never throws
diff --git a/boost/interprocess/allocators/detail/node_pool.hpp b/boost/interprocess/allocators/detail/node_pool.hpp
index 562b64863b..cee9cdafc8 100644
--- a/boost/interprocess/allocators/detail/node_pool.hpp
+++ b/boost/interprocess/allocators/detail/node_pool.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP
#define BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -19,8 +19,6 @@
#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>
@@ -37,7 +35,7 @@ namespace ipcdetail {
//!Pooled shared memory allocator using single segregated storage. Includes
-//!a reference count but the class does not delete itself, this is
+//!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 >
@@ -73,11 +71,11 @@ class private_node_pool
//!Pooled shared memory allocator using single segregated storage. Includes
-//!a reference count but the class does not delete itself, this is
+//!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
+//!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
diff --git a/boost/interprocess/allocators/detail/node_tools.hpp b/boost/interprocess/allocators/detail/node_tools.hpp
index da7e4668e8..e7115ece4e 100644
--- a/boost/interprocess/allocators/detail/node_tools.hpp
+++ b/boost/interprocess/allocators/detail/node_tools.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2007-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP
#define BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/allocators/node_allocator.hpp b/boost/interprocess/allocators/node_allocator.hpp
index 2c1fe566a3..af522f35b2 100644
--- a/boost/interprocess/allocators/node_allocator.hpp
+++ b/boost/interprocess/allocators/node_allocator.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP
#define BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -39,7 +39,7 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail{
@@ -63,7 +63,7 @@ class node_allocator_base
typedef node_allocator_base
<Version, T, SegmentManager, NodesPerBlock> self_t;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template <int dummy>
struct node_pool
@@ -74,7 +74,7 @@ class node_allocator_base
static type *get(void *p)
{ return static_cast<type*>(p); }
};
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
BOOST_STATIC_ASSERT((Version <=2));
@@ -102,11 +102,11 @@ class node_allocator_base
//!node_allocator_base
template<class T2>
struct rebind
- {
+ {
typedef node_allocator_base<Version, T2, SegmentManager, NodesPerBlock> other;
};
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
//!Not assignable from related node_allocator_base
template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2>
@@ -115,7 +115,7 @@ class node_allocator_base
//!Not assignable from other node_allocator_base
//node_allocator_base& operator=(const node_allocator_base&);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor from a segment manager. If not present, constructs a node
@@ -128,8 +128,8 @@ class node_allocator_base
//!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();
+ {
+ 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
@@ -168,10 +168,10 @@ class node_allocator_base
friend void swap(self_t &alloc1, self_t &alloc2)
{ ipcdetail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
void_pointer mp_node_pool;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!Equality test for same type
@@ -206,7 +206,7 @@ class node_allocator_v1
template<class T2>
struct rebind
- {
+ {
typedef node_allocator_v1<T2, SegmentManager, NodesPerBlock> other;
};
@@ -223,7 +223,7 @@ class node_allocator_v1
} //namespace ipcdetail{
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!An STL node allocator that uses a segment manager as memory
//!source. The internal pointer type will of the same type (raw, smart) as
@@ -232,20 +232,20 @@ class node_allocator_v1
//!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
+//!runs out of nodes
template < class T
, class SegmentManager
, std::size_t NodesPerBlock
>
class node_allocator
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
: public ipcdetail::node_allocator_base
< 2
, T
, SegmentManager
, NodesPerBlock
>
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
{
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -256,7 +256,7 @@ class node_allocator
template<class T2>
struct rebind
- {
+ {
typedef node_allocator<T2, SegmentManager, NodesPerBlock> other;
};
@@ -288,7 +288,7 @@ class node_allocator
//!node_allocator
template<class T2>
struct rebind
- {
+ {
typedef node_allocator<T2, SegmentManager, NodesPerBlock> other;
};
@@ -385,12 +385,12 @@ class node_allocator
//!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);
+ void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
- multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -398,7 +398,7 @@ class node_allocator
//!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);
+ void deallocate_many(multiallocation_chain &chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -411,7 +411,7 @@ class node_allocator
//!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);
+ void allocate_individual(size_type num_elements, multiallocation_chain &chain);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -424,7 +424,7 @@ class node_allocator
//!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);
+ void deallocate_individual(multiallocation_chain &chain);
#endif
};
diff --git a/boost/interprocess/allocators/private_adaptive_pool.hpp b/boost/interprocess/allocators/private_adaptive_pool.hpp
index febe85c69d..529dc9d138 100644
--- a/boost/interprocess/allocators/private_adaptive_pool.hpp
+++ b/boost/interprocess/allocators/private_adaptive_pool.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP
#define BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -38,7 +38,7 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail {
@@ -63,7 +63,7 @@ class private_adaptive_pool_base
typedef SegmentManager segment_manager;
typedef typename SegmentManager::void_pointer void_pointer;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef private_adaptive_pool_base
< Version, T, SegmentManager, NodesPerBlock
@@ -78,7 +78,7 @@ class private_adaptive_pool_base
BOOST_STATIC_ASSERT((Version <=2));
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
typedef typename boost::intrusive::
@@ -102,12 +102,12 @@ class private_adaptive_pool_base
//!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
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template <int dummy>
struct node_pool
@@ -132,7 +132,7 @@ class private_adaptive_pool_base
//!Not assignable from other private_adaptive_pool_base
private_adaptive_pool_base& operator=(const private_adaptive_pool_base&);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor from a segment manager
@@ -170,10 +170,10 @@ class private_adaptive_pool_base
friend void swap(self_t &alloc1,self_t &alloc2)
{ alloc1.m_node_pool.swap(alloc2.m_node_pool); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
node_pool_t m_node_pool;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!Equality test for same type of private_adaptive_pool_base
@@ -210,7 +210,7 @@ class private_adaptive_pool_v1
template<class T2>
struct rebind
- {
+ {
typedef private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
};
@@ -227,7 +227,7 @@ class private_adaptive_pool_v1
} //namespace ipcdetail {
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!An STL node allocator that uses a segment manager as memory
//!source. The internal pointer type will of the same type (raw, smart) as
@@ -249,7 +249,7 @@ template < class T
, unsigned char OverheadPercent
>
class private_adaptive_pool
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
: public ipcdetail::private_adaptive_pool_base
< 2
, T
@@ -258,7 +258,7 @@ class private_adaptive_pool
, MaxFreeBlocks
, OverheadPercent
>
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
{
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -269,7 +269,7 @@ class private_adaptive_pool
template<class T2>
struct rebind
- {
+ {
typedef private_adaptive_pool
<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
};
@@ -302,7 +302,7 @@ class private_adaptive_pool
//!private_adaptive_pool
template<class T2>
struct rebind
- {
+ {
typedef private_adaptive_pool
<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
};
@@ -400,12 +400,12 @@ class private_adaptive_pool
//!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);
+ void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
- multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -413,7 +413,7 @@ class private_adaptive_pool
//!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);
+ void deallocate_many(multiallocation_chain &chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -426,7 +426,7 @@ class private_adaptive_pool
//!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);
+ void allocate_individual(size_type num_elements, multiallocation_chain &chain);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -439,7 +439,7 @@ class private_adaptive_pool
//!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);
+ void deallocate_individual(multiallocation_chain &chain);
#endif
};
diff --git a/boost/interprocess/allocators/private_node_allocator.hpp b/boost/interprocess/allocators/private_node_allocator.hpp
index 46b7dd6097..8b546c3354 100644
--- a/boost/interprocess/allocators/private_node_allocator.hpp
+++ b/boost/interprocess/allocators/private_node_allocator.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP
#define BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -38,7 +38,7 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail {
@@ -60,7 +60,7 @@ class private_node_allocator_base
typedef SegmentManager segment_manager;
typedef typename SegmentManager::void_pointer void_pointer;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef private_node_allocator_base
< Version, T, SegmentManager, NodesPerBlock> self_t;
@@ -72,7 +72,7 @@ class private_node_allocator_base
BOOST_STATIC_ASSERT((Version <=2));
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
@@ -97,12 +97,12 @@ class private_node_allocator_base
//!Obtains node_allocator from other node_allocator
template<class T2>
struct rebind
- {
+ {
typedef private_node_allocator_base
<Version, T2, SegmentManager, NodesPerBlock> other;
};
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template <int dummy>
struct node_pool
{
@@ -124,7 +124,7 @@ class private_node_allocator_base
//!Not assignable from other private_node_allocator_base
private_node_allocator_base& operator=(const private_node_allocator_base&);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor from a segment manager
@@ -162,10 +162,10 @@ class private_node_allocator_base
friend void swap(self_t &alloc1,self_t &alloc2)
{ alloc1.m_node_pool.swap(alloc2.m_node_pool); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
node_pool_t m_node_pool;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!Equality test for same type of private_node_allocator_base
@@ -198,7 +198,7 @@ class private_node_allocator_v1
template<class T2>
struct rebind
- {
+ {
typedef private_node_allocator_v1<T2, SegmentManager, NodesPerBlock> other;
};
@@ -215,7 +215,7 @@ class private_node_allocator_v1
} //namespace ipcdetail {
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!An STL node allocator that uses a segment manager as memory
//!source. The internal pointer type will of the same type (raw, smart) as
@@ -228,14 +228,14 @@ template < class T
, std::size_t NodesPerBlock
>
class private_node_allocator
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
: public ipcdetail::private_node_allocator_base
< 2
, T
, SegmentManager
, NodesPerBlock
>
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
{
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -246,7 +246,7 @@ class private_node_allocator
template<class T2>
struct rebind
- {
+ {
typedef private_node_allocator
<T2, SegmentManager, NodesPerBlock> other;
};
@@ -279,7 +279,7 @@ class private_node_allocator
//!private_node_allocator
template<class T2>
struct rebind
- {
+ {
typedef private_node_allocator
<T2, SegmentManager, NodesPerBlock> other;
};
@@ -377,12 +377,12 @@ class private_node_allocator
//!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);
+ void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
- multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -390,7 +390,7 @@ class private_node_allocator
//!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);
+ void deallocate_many(multiallocation_chain &chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -403,7 +403,7 @@ class private_node_allocator
//!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);
+ void allocate_individual(size_type num_elements, multiallocation_chain &chain);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -416,7 +416,7 @@ class private_node_allocator
//!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);
+ void deallocate_individual(multiallocation_chain &chain);
#endif
};
diff --git a/boost/interprocess/anonymous_shared_memory.hpp b/boost/interprocess/anonymous_shared_memory.hpp
index 624f57f9c3..aed868fb62 100644
--- a/boost/interprocess/anonymous_shared_memory.hpp
+++ b/boost/interprocess/anonymous_shared_memory.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP
#define BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/creation_tags.hpp>
@@ -35,7 +39,7 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail{
@@ -53,7 +57,7 @@ namespace ipcdetail{
};
}
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!A function that creates an anonymous shared memory segment of size "size".
//!If "address" is passed the function will try to map the segment in that address.
@@ -90,13 +94,13 @@ anonymous_shared_memory(std::size_t size, void *address = 0)
, 0);
if(address == MAP_FAILED){
- if(fd != -1)
+ if(fd != -1)
close(fd);
error_info err = system_error_code();
throw interprocess_exception(err);
}
- if(fd != -1)
+ if(fd != -1)
close(fd);
return ipcdetail::raw_mapped_region_creator::create_posix_mapped_region(address, size);
diff --git a/boost/interprocess/containers/allocation_type.hpp b/boost/interprocess/containers/allocation_type.hpp
index 660b6cbdbc..cae9612fb4 100644
--- a/boost/interprocess/containers/allocation_type.hpp
+++ b/boost/interprocess/containers/allocation_type.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP
#define BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -21,9 +21,9 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef int allocation_type;
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
static const allocation_type allocate_new = boost::container::allocate_new;
static const allocation_type expand_fwd = boost::container::expand_fwd;
static const allocation_type expand_bwd = boost::container::expand_bwd;
diff --git a/boost/interprocess/containers/containers_fwd.hpp b/boost/interprocess/containers/containers_fwd.hpp
index 7852bbc853..4175390599 100644
--- a/boost/interprocess/containers/containers_fwd.hpp
+++ b/boost/interprocess/containers/containers_fwd.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,9 +11,9 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP
#define BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -35,6 +35,6 @@ using boost::container::ordered_unique_range;
#include <boost/interprocess/detail/config_end.hpp>
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP
diff --git a/boost/interprocess/containers/deque.hpp b/boost/interprocess/containers/deque.hpp
index 30ca43203f..a40db80a19 100644
--- a/boost/interprocess/containers/deque.hpp
+++ b/boost/interprocess/containers/deque.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP
#define BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/containers/flat_map.hpp b/boost/interprocess/containers/flat_map.hpp
index f18a006c79..744d6e972e 100644
--- a/boost/interprocess/containers/flat_map.hpp
+++ b/boost/interprocess/containers/flat_map.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP
#define BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/containers/flat_set.hpp b/boost/interprocess/containers/flat_set.hpp
index 1b2bf9b4d3..51c49925c0 100644
--- a/boost/interprocess/containers/flat_set.hpp
+++ b/boost/interprocess/containers/flat_set.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP
#define BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/containers/list.hpp b/boost/interprocess/containers/list.hpp
index a75b9759b3..0e855efaaf 100644
--- a/boost/interprocess/containers/list.hpp
+++ b/boost/interprocess/containers/list.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_LIST_HPP
#define BOOST_INTERPROCESS_CONTAINERS_LIST_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/containers/map.hpp b/boost/interprocess/containers/map.hpp
index 2e45ec0630..4efed89c10 100644
--- a/boost/interprocess/containers/map.hpp
+++ b/boost/interprocess/containers/map.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_MAP_HPP
#define BOOST_INTERPROCESS_CONTAINERS_MAP_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/containers/pair.hpp b/boost/interprocess/containers/pair.hpp
index 8ba6d047ac..2ca631db4a 100644
--- a/boost/interprocess/containers/pair.hpp
+++ b/boost/interprocess/containers/pair.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP
#define BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/containers/set.hpp b/boost/interprocess/containers/set.hpp
index db06afea6d..09ea6c116d 100644
--- a/boost/interprocess/containers/set.hpp
+++ b/boost/interprocess/containers/set.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_SET_HPP
#define BOOST_INTERPROCESS_CONTAINERS_SET_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/containers/slist.hpp b/boost/interprocess/containers/slist.hpp
index f93379cb7a..c3e1744ea3 100644
--- a/boost/interprocess/containers/slist.hpp
+++ b/boost/interprocess/containers/slist.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP
#define BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/containers/stable_vector.hpp b/boost/interprocess/containers/stable_vector.hpp
index ae09e6b52f..530056dd6e 100644
--- a/boost/interprocess/containers/stable_vector.hpp
+++ b/boost/interprocess/containers/stable_vector.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP
#define BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/containers/string.hpp b/boost/interprocess/containers/string.hpp
index a11bb904b4..805bfe4f14 100644
--- a/boost/interprocess/containers/string.hpp
+++ b/boost/interprocess/containers/string.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_STRING_HPP
#define BOOST_INTERPROCESS_CONTAINERS_STRING_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/containers/vector.hpp b/boost/interprocess/containers/vector.hpp
index 3a6b411512..bfae4f833f 100644
--- a/boost/interprocess/containers/vector.hpp
+++ b/boost/interprocess/containers/vector.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP
#define BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/containers/version_type.hpp b/boost/interprocess/containers/version_type.hpp
index 247f800f4a..92ef49f31d 100644
--- a/boost/interprocess/containers/version_type.hpp
+++ b/boost/interprocess/containers/version_type.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
#define BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/creation_tags.hpp b/boost/interprocess/creation_tags.hpp
index 374829ac2b..9ff27bffa0 100644
--- a/boost/interprocess/creation_tags.hpp
+++ b/boost/interprocess/creation_tags.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_CREATION_TAGS_HPP
#define BOOST_INTERPROCESS_CREATION_TAGS_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
diff --git a/boost/interprocess/detail/atomic.hpp b/boost/interprocess/detail/atomic.hpp
index aab1533985..96b7729d7e 100644
--- a/boost/interprocess/detail/atomic.hpp
+++ b/boost/interprocess/detail/atomic.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2006-2011
+// (C) Copyright Ion Gaztanaga 2006-2012
// (C) Copyright Markus Schoepflin 2007
// (C) Copyright Bryce Lelbach 2010
//
@@ -15,6 +15,10 @@
#ifndef BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
#define BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/cstdint.hpp>
@@ -49,10 +53,22 @@ inline boost::uint32_t atomic_cas32
} //namespace interprocess{
} //namespace boost{
-#if (defined BOOST_INTERPROCESS_WINDOWS)
+#if defined (BOOST_INTERPROCESS_WINDOWS)
#include <boost/interprocess/detail/win32_api.hpp>
+#if defined( _MSC_VER )
+ extern "C" void _ReadWriteBarrier(void);
+ #pragma intrinsic(_ReadWriteBarrier)
+ #define BOOST_INTERPROCESS_READ_WRITE_BARRIER _ReadWriteBarrier()
+#elif defined(__GNUC__)
+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
+ #define BOOST_INTERPROCESS_READ_WRITE_BARRIER __sync_synchronize()
+ #else
+ #define BOOST_INTERPROCESS_READ_WRITE_BARRIER __asm__ __volatile__("" : : : "memory")
+ #endif
+#endif
+
namespace boost{
namespace interprocess{
namespace ipcdetail{
@@ -71,7 +87,11 @@ 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)
-{ return *mem; }
+{
+ const boost::uint32_t val = *mem;
+ BOOST_INTERPROCESS_READ_WRITE_BARRIER;
+ return val;
+}
//! Atomically set an boost::uint32_t in memory
//! "mem": pointer to the object
@@ -93,7 +113,7 @@ inline boost::uint32_t atomic_cas32
} //namespace interprocess{
} //namespace boost{
-#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(_CRAYC)
namespace boost {
namespace interprocess {
@@ -157,13 +177,24 @@ inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
//! Atomically read an boost::uint32_t from memory
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
-{ return *mem; }
+{
+ const boost::uint32_t val = *mem;
+ __asm__ __volatile__ ( "" ::: "memory" );
+ return val;
+}
//! 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; }
+{
+ __asm__ __volatile__
+ (
+ "xchgl %0, %1"
+ : "+r" (val), "+m" (*mem)
+ :: "memory"
+ );
+}
} //namespace ipcdetail{
} //namespace interprocess{
@@ -213,7 +244,7 @@ inline boost::uint32_t atomic_cas32
"bne- 1b\n\t"
"2:"
: "=&r"(prev)
- : "b" (mem), "r"(cmp), "r" (with)
+ : "b" (mem), "r" (with), "r" (cmp)
: "cc", "memory");
return prev;
}
@@ -232,7 +263,11 @@ inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
//! Atomically read an boost::uint32_t from memory
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
-{ return *mem; }
+{
+ const boost::uint32_t val = *mem;
+ __asm__ __volatile__ ( "" ::: "memory" );
+ return val;
+}
//! Atomically set an boost::uint32_t in memory
//! "mem": pointer to the object
@@ -390,96 +425,96 @@ inline boost::uint32_t atomic_cas32(
} //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
+#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
#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
@@ -510,7 +545,7 @@ inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
//! Atomically read an boost::uint32_t from memory
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
-{ return *mem; }
+{ boost::uint32_t old_val = *mem; __sync_synchronize(); return old_val; }
//! Compare an boost::uint32_t's value with "cmp".
//! If they are the same swap the value with "with"
@@ -526,7 +561,7 @@ inline boost::uint32_t atomic_cas32
//! "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; }
+{ __sync_synchronize(); *mem = val; }
} //namespace ipcdetail{
} //namespace interprocess{
@@ -552,9 +587,9 @@ inline bool atomic_add_unless32
return c != unless_this;
}
-} //namespace ipcdetail
-} //namespace interprocess
-} //namespace boost
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
#include <boost/interprocess/detail/config_end.hpp>
diff --git a/boost/interprocess/detail/cast_tags.hpp b/boost/interprocess/detail/cast_tags.hpp
index bd91d1b6bb..0019af7933 100644
--- a/boost/interprocess/detail/cast_tags.hpp
+++ b/boost/interprocess/detail/cast_tags.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP
#define BOOST_INTERPROCESS_CAST_TAGS_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
diff --git a/boost/interprocess/detail/config_begin.hpp b/boost/interprocess/detail/config_begin.hpp
index a72f6df1fe..8bcdcac587 100644
--- a/boost/interprocess/detail/config_begin.hpp
+++ b/boost/interprocess/detail/config_begin.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -13,10 +13,6 @@
#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
diff --git a/boost/interprocess/detail/config_end.hpp b/boost/interprocess/detail/config_end.hpp
index 422458e855..28ec407312 100644
--- a/boost/interprocess/detail/config_end.hpp
+++ b/boost/interprocess/detail/config_end.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -9,9 +9,5 @@
//////////////////////////////////////////////////////////////////////////////
#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/config_external_begin.hpp b/boost/interprocess/detail/config_external_begin.hpp
new file mode 100644
index 0000000000..fb578ef013
--- /dev/null
+++ b/boost/interprocess/detail/config_external_begin.hpp
@@ -0,0 +1,18 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_INTERPROCESS_EXTERNAL_CONFIG_INCLUDED
+#define BOOST_INTERPROCESS_EXTERNAL_CONFIG_INCLUDED
+#include <boost/config.hpp>
+#endif
+
+#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wshadow"
+#endif
diff --git a/boost/interprocess/detail/config_external_end.hpp b/boost/interprocess/detail/config_external_end.hpp
new file mode 100644
index 0000000000..214558f58c
--- /dev/null
+++ b/boost/interprocess/detail/config_external_end.hpp
@@ -0,0 +1,12 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406)
+# pragma GCC diagnostic pop
+#endif
diff --git a/boost/interprocess/detail/file_locking_helpers.hpp b/boost/interprocess/detail/file_locking_helpers.hpp
index 2b96e2b6d5..6a7ce8ef3b 100644
--- a/boost/interprocess/detail/file_locking_helpers.hpp
+++ b/boost/interprocess/detail/file_locking_helpers.hpp
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP
#define BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP
-#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#if defined(_MSC_VER)
#pragma once
#endif
@@ -26,7 +26,7 @@
#include <cstddef>
#include <boost/interprocess/detail/os_file_functions.hpp>
-#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/detail/shared_dir_helpers.hpp>
#if defined(BOOST_INTERPROCESS_WINDOWS)
@@ -287,7 +287,7 @@ inline bool compare_file_serial(int fd, const locking_file_serial_id &id)
id.st_ino == info.st_ino;
}
-#endif
+#endif
} //namespace ipcdetail{
} //namespace interprocess{
diff --git a/boost/interprocess/detail/file_wrapper.hpp b/boost/interprocess/detail/file_wrapper.hpp
index 586e20db4d..507ec478dc 100644
--- a/boost/interprocess/detail/file_wrapper.hpp
+++ b/boost/interprocess/detail/file_wrapper.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,11 +11,15 @@
#ifndef BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP
#define BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#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/move/utility_core.hpp>
#include <boost/interprocess/creation_tags.hpp>
namespace boost {
@@ -24,9 +28,9 @@ namespace ipcdetail{
class file_wrapper
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
BOOST_MOVABLE_BUT_NOT_COPYABLE(file_wrapper)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Default constructor.
@@ -60,10 +64,10 @@ class file_wrapper
//!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;
+ return *this;
}
//!Swaps to file_wrappers.
@@ -73,7 +77,7 @@ class file_wrapper
//!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);
@@ -122,10 +126,10 @@ 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);
+ m_filename.swap(other.m_filename);
}
inline mapping_handle_t file_wrapper::get_mapping_handle() const
@@ -167,7 +171,8 @@ inline bool file_wrapper::priv_open_or_create
//Check for error
if(m_handle == invalid_file()){
- throw interprocess_exception(error_info(system_error_code()));
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
}
m_mode = mode;
diff --git a/boost/interprocess/detail/in_place_interface.hpp b/boost/interprocess/detail/in_place_interface.hpp
index b43b2ce165..5af5a0d2df 100644
--- a/boost/interprocess/detail/in_place_interface.hpp
+++ b/boost/interprocess/detail/in_place_interface.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
#define BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -47,7 +47,7 @@ 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())
+ : 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)
diff --git a/boost/interprocess/detail/intermodule_singleton.hpp b/boost/interprocess/detail/intermodule_singleton.hpp
index 054322699d..a99934893d 100644
--- a/boost/interprocess/detail/intermodule_singleton.hpp
+++ b/boost/interprocess/detail/intermodule_singleton.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_HPP
#define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_HPP
-#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#if defined(_MSC_VER)
#pragma once
#endif
@@ -20,8 +20,9 @@
#ifdef BOOST_INTERPROCESS_WINDOWS
#include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
+#else
+ #include <boost/interprocess/detail/portable_intermodule_singleton.hpp>
#endif
-#include <boost/interprocess/detail/portable_intermodule_singleton.hpp>
namespace boost{
namespace interprocess{
@@ -30,7 +31,7 @@ namespace ipcdetail{
//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 = true, bool Phoenix = true>
+template<typename C, bool LazyInit = true, bool Phoenix = false>
class intermodule_singleton
#ifdef BOOST_INTERPROCESS_WINDOWS
: public windows_intermodule_singleton<C, LazyInit, Phoenix>
diff --git a/boost/interprocess/detail/intermodule_singleton_common.hpp b/boost/interprocess/detail/intermodule_singleton_common.hpp
index 0710c0bbc1..10c9eceabb 100644
--- a/boost/interprocess/detail/intermodule_singleton_common.hpp
+++ b/boost/interprocess/detail/intermodule_singleton_common.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
#define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
-#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#if defined(_MSC_VER)
#pragma once
#endif
@@ -20,8 +20,10 @@
#include <boost/interprocess/detail/atomic.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/exceptions.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/sync/spin/wait.hpp>
#include <boost/assert.hpp>
#include <cstddef>
#include <cstdio>
@@ -121,7 +123,8 @@ class intermodule_singleton_common
//Now try to create the singleton in global map.
//This function solves concurrency issues
//between threads of several modules
- void *tmp = constructor(get_map());
+ ThreadSafeGlobalMap *const pmap = get_map_ptr();
+ void *tmp = constructor(*pmap);
//Increment the module reference count that reflects how many
//singletons this module holds, so that we can safely destroy
//module global map object when no singleton is left
@@ -144,6 +147,7 @@ class intermodule_singleton_common
//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){
+ spin_wait swait;
while(1){
previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized);
if(previous_module_singleton_initialized >= Initialized){
@@ -151,7 +155,7 @@ class intermodule_singleton_common
break;
}
else if(previous_module_singleton_initialized == Initializing){
- thread_yield();
+ swait.yield();
}
else{
//This can't be happening!
@@ -178,7 +182,8 @@ class intermodule_singleton_common
//Note: this destructor might provoke a Phoenix singleton
//resurrection. This means that this_module_singleton_count
//might change after this call.
- destructor(ptr, get_map());
+ ThreadSafeGlobalMap * const pmap = get_map_ptr();
+ destructor(ptr, *pmap);
ptr = 0;
//Memory barrier to make sure pointer is nulled.
@@ -197,14 +202,15 @@ class intermodule_singleton_common
}
private:
- static ThreadSafeGlobalMap &get_map()
+ static ThreadSafeGlobalMap *get_map_ptr()
{
- return *static_cast<ThreadSafeGlobalMap *>(static_cast<void *>(&mem_holder.map_mem));
+ return static_cast<ThreadSafeGlobalMap *>(static_cast<void*>(mem_holder.map_mem));
}
static void initialize_global_map_handle()
{
//Obtain unique map name and size
+ spin_wait swait;
while(1){
//Try to pass map state to initializing
::boost::uint32_t tmp = atomic_cas32(&this_module_map_initialized, Initializing, Uninitialized);
@@ -217,7 +223,7 @@ class intermodule_singleton_common
}
//If some other thread is doing the work wait
else if(tmp == Initializing){
- thread_yield();
+ swait.yield();
}
else{ //(tmp == Uninitialized)
//If not initialized try it again?
@@ -225,16 +231,17 @@ class intermodule_singleton_common
//Remove old global map from the system
intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem();
//in-place construction of the global map class
+ ThreadSafeGlobalMap * const pmap = get_map_ptr();
intermodule_singleton_helpers::thread_safe_global_map_dependant
- <ThreadSafeGlobalMap>::construct_map(static_cast<void*>(&get_map()));
+ <ThreadSafeGlobalMap>::construct_map(static_cast<void*>(pmap));
//Use global map's internal lock to initialize the lock file
//that will mark this gmem as "in use".
typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::
- lock_file_logic f(get_map());
+ lock_file_logic f(*pmap);
//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()){
- get_map().~ThreadSafeGlobalMap();
+ pmap->~ThreadSafeGlobalMap();
atomic_write32(&this_module_map_initialized, Destroyed);
}
else{
@@ -257,9 +264,10 @@ class intermodule_singleton_common
//This module is being unloaded, so destroy
//the global map object of this module
//and unlink the global map if it's the last
+ ThreadSafeGlobalMap * const pmap = get_map_ptr();
typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::
- unlink_map_logic f(get_map());
- (get_map()).~ThreadSafeGlobalMap();
+ unlink_map_logic f(*pmap);
+ pmap->~ThreadSafeGlobalMap();
atomic_write32(&this_module_map_initialized, Destroyed);
//Do some cleanup for other processes old gmem instances
intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem();
@@ -274,11 +282,11 @@ class intermodule_singleton_common
//Values: Uninitialized, Initializing, Initialized, Broken
static volatile boost::uint32_t this_module_map_initialized;
- //Raw memory to construct the global map manager
- static struct mem_holder_t
+ //Raw memory to construct the global map manager
+ static union mem_holder_t
{
+ unsigned char map_mem [sizeof(ThreadSafeGlobalMap)];
::boost::detail::max_align aligner;
- char map_mem [sizeof(ThreadSafeGlobalMap)];
} mem_holder;
};
@@ -308,7 +316,7 @@ struct ref_count_ptr
//Now this class is a singleton, initializing the singleton in
-//the first get() function call if LazyInit is false. If true
+//the first get() function call if LazyInit is true. If false
//then the singleton will be initialized when loading the module.
template<typename C, bool LazyInit, bool Phoenix, class ThreadSafeGlobalMap>
class intermodule_singleton_impl
@@ -356,9 +364,9 @@ class intermodule_singleton_impl
~lifetime_type_lazy()
{
- if(!Phoenix){
- atexit_work();
- }
+ //if(!Phoenix){
+ //atexit_work();
+ //}
}
//Dummy volatile so that the compiler can't resolve its value at compile-time
@@ -384,7 +392,7 @@ class intermodule_singleton_impl
struct init_atomic_func
{
init_atomic_func(ThreadSafeGlobalMap &m)
- : m_map(m)
+ : m_map(m), ret_ptr()
{}
void operator()()
@@ -405,13 +413,13 @@ class intermodule_singleton_impl
throw;
}
}
- if(Phoenix){
+ //if(Phoenix){
std::atexit(&atexit_work);
- }
+ //}
atomic_inc32(&rcount->singleton_ref_count);
ret_ptr = rcount->ptr;
}
- void *data() const
+ void *data() const
{ return ret_ptr; }
private:
@@ -446,12 +454,9 @@ class intermodule_singleton_impl
delete pc;
}
}
- void *data() const
- { return ret_ptr; }
-
+
private:
ThreadSafeGlobalMap &m_map;
- void *ret_ptr;
};
//A wrapper to execute init_atomic_func
diff --git a/boost/interprocess/detail/interprocess_tester.hpp b/boost/interprocess/detail/interprocess_tester.hpp
index 2581776745..8c00c4c0c4 100644
--- a/boost/interprocess/detail/interprocess_tester.hpp
+++ b/boost/interprocess/detail/interprocess_tester.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2007-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP
#define BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
namespace boost{
namespace interprocess{
namespace ipcdetail{
diff --git a/boost/interprocess/detail/intersegment_ptr.hpp b/boost/interprocess/detail/intersegment_ptr.hpp
index 16d3505883..fa1b277ef4 100644
--- a/boost/interprocess/detail/intersegment_ptr.hpp
+++ b/boost/interprocess/detail/intersegment_ptr.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP
#define BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -177,7 +177,7 @@ struct intersegment_base
void set_mode(std::size_t mode)
{
- BOOST_ASSERT(mode < is_max_mode);
+ BOOST_ASSERT(mode < is_max_mode);
members.direct.ctrl = mode;
}
@@ -309,13 +309,13 @@ struct flat_map_intersegment
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);
+ 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);
@@ -383,7 +383,7 @@ struct flat_map_intersegment
};
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)
@@ -445,7 +445,7 @@ struct flat_map_intersegment
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()
@@ -486,7 +486,7 @@ struct flat_map_intersegment
--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;
@@ -552,7 +552,7 @@ struct flat_map_intersegment
s_groups.insert(segment_group_t(*services));
BOOST_ASSERT(ret.second);
return &*ret.first;
- }
+ }
}
static bool delete_group(segment_group_id id)
@@ -574,7 +574,7 @@ struct flat_map_intersegment
}
}
return success;
- }
+ }
}
};
@@ -663,17 +663,17 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex>
//!Pointer-like -> operator. It can return 0 pointer.
//!Never throws.
- pointer operator->() const
+ pointer operator->() const
{ return self_t::get(); }
//!Dereferencing operator, if it is a null intersegment_ptr behavior
//!is undefined. Never throws.
- reference operator* () const
+ reference operator* () const
{ return *(self_t::get()); }
//!Indexing operator.
//!Never throws.
- reference operator[](std::ptrdiff_t idx) const
+ reference operator[](std::ptrdiff_t idx) const
{ return self_t::get()[idx]; }
//!Assignment from pointer (saves extra conversion).
@@ -690,15 +690,15 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex>
//!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;
+ 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 operator+ (std::ptrdiff_t idx) const
+ {
intersegment_ptr result (*this);
result.inc_offset(idx*sizeof(T));
return result;
@@ -706,8 +706,8 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex>
//!intersegment_ptr - std::ptrdiff_t.
//!Never throws.
- intersegment_ptr operator- (std::ptrdiff_t idx) const
- {
+ intersegment_ptr operator- (std::ptrdiff_t idx) const
+ {
intersegment_ptr result (*this);
result.dec_offset(idx*sizeof(T));
return result;
@@ -745,7 +745,7 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex>
//!Safe bool conversion operator.
//!Never throws.
- operator unspecified_bool_type() const
+ 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.
@@ -784,12 +784,12 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex>
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);
+ return left._equal(right);
}
//!Returns true if *this is less than other.
@@ -798,12 +798,12 @@ bool operator ==(const intersegment_ptr<T1> &left,
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);
+ return left._less(right);
}
template<class T1, class T2> inline
diff --git a/boost/interprocess/detail/managed_global_memory.hpp b/boost/interprocess/detail/managed_global_memory.hpp
index 39dd0b1e6d..baa6361e69 100644
--- a/boost/interprocess/detail/managed_global_memory.hpp
+++ b/boost/interprocess/detail/managed_global_memory.hpp
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP
#define BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP
-#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#if defined(_MSC_VER)
#pragma once
#endif
@@ -23,7 +23,7 @@
#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/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/indexes/iset_index.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/permissions.hpp>
@@ -47,7 +47,7 @@ struct intermodule_types
struct open_or_create
{
typedef managed_open_or_create_impl
- <Device, mem_algo::Alignment, FileBased> type;
+ <Device, mem_algo::Alignment, FileBased, false> type;
};
};
@@ -62,7 +62,7 @@ class basic_managed_global_memory
>
, private intermodule_types::open_or_create<Device, FileBased>::type
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef typename intermodule_types::template open_or_create<Device, FileBased>::type base2_t;
typedef basic_managed_memory_impl
@@ -83,7 +83,7 @@ class basic_managed_global_memory
private:
typedef typename base_t::char_ptr_holder_t char_ptr_holder_t;
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_global_memory)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public: //functions
diff --git a/boost/interprocess/detail/managed_memory_impl.hpp b/boost/interprocess/detail/managed_memory_impl.hpp
index f9ecb8a860..b77c53274d 100644
--- a/boost/interprocess/detail/managed_memory_impl.hpp
+++ b/boost/interprocess/detail/managed_memory_impl.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
#define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -90,7 +90,7 @@ class basic_managed_memory_impl
typedef typename segment_manager::
const_unique_iterator const_unique_iterator;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef typename
segment_manager::char_ptr_holder_t char_ptr_holder_t;
@@ -98,7 +98,7 @@ class basic_managed_memory_impl
typedef typename segment_manager::multiallocation_chain multiallocation_chain;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation;
@@ -172,14 +172,14 @@ class basic_managed_memory_impl
//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
+ //Let's construct the allocator in memory
mp_header = new(addr) segment_manager(size);
}
BOOST_CATCH(...){
return false;
}
BOOST_CATCH_END
- return true;
+ return true;
}
//!Connects to a segment manager in the reserved buffer. Never throws.
@@ -192,7 +192,7 @@ class basic_managed_memory_impl
//!Frees resources. Never throws.
bool close_impl()
- {
+ {
bool ret = mp_header != 0;
mp_header = 0;
return ret;
@@ -254,12 +254,12 @@ class basic_managed_memory_impl
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()));
+ 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());
}
@@ -292,7 +292,7 @@ class basic_managed_memory_impl
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);
}
@@ -303,31 +303,37 @@ class basic_managed_memory_impl
void * allocate_aligned(size_type nbytes, size_type alignment)
{ return mp_header->allocate_aligned(nbytes, alignment); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//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 of elem_bytes bytes.
+ //!Throws bad_alloc on failure. chain.size() is not increased on failure.
+ void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
+ { mp_header->allocate_many(elem_bytes, n_elements, chain); }
- //!Allocates n_elements, each one of 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, each one of element_lengths[i]*sizeof_element bytes.
+ //!Throws bad_alloc on failure. chain.size() is not increased on failure.
+ void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
+ { mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); }
- //!Allocates n_elements of elem_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 of elem_bytes bytes.
+ //!Non-throwing version. chain.size() is not increased on failure.
+ void allocate_many(std::nothrow_t, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
+ { mp_header->allocate_many(std::nothrow_t(), elem_bytes, n_elements, chain); }
- //!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
+ //!element_lengths[i]*sizeof_element bytes.
+ //!Non-throwing version. chain.size() is not increased on failure.
+ void allocate_many(std::nothrow_t, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
+ { mp_header->allocate_many(std::nothrow_t(), elem_sizes, n_elements, sizeof_element, chain); }
- //!Allocates n_elements, each one of elem_sizes[i] bytes.
- void deallocate_many(multiallocation_chain chain)
- { return mp_header->deallocate_many(boost::move(chain)); }
+ //!Deallocates all elements contained in chain.
+ //!Never throws.
+ void deallocate_many(multiallocation_chain &chain)
+ { mp_header->deallocate_many(chain); }
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Marks previously allocated memory as free. Never throws.
void deallocate (void *addr)
@@ -603,7 +609,7 @@ class basic_managed_memory_impl
{ mp_header->template destroy_ptr<T>(ptr); }
//!Returns the name of an object created with construct/find_or_construct
- //!functions. Does not throw
+ //!functions. If ptr points to an unique instance typeid(T).name() is returned.
template<class T>
static const char_type *get_instance_name(const T *ptr)
{ return segment_manager::get_instance_name(ptr); }
@@ -697,14 +703,14 @@ class basic_managed_memory_impl
get_deleter()
{ return mp_header->template get_deleter<T>(); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Tries to find a previous named allocation address. Returns a memory
//!buffer and the object count. If not found returned pointer is 0.
//!Never throws.
template <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
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
protected:
//!Swaps the segment manager's managed by this managed memory segment.
@@ -719,20 +725,40 @@ class basic_managed_memory_impl
template<class BasicManagedMemoryImpl>
class create_open_func
{
+ typedef typename BasicManagedMemoryImpl::size_type size_type;
+
public:
+
create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type)
: m_frontend(frontend), m_type(type){}
- bool operator()(void *addr, typename BasicManagedMemoryImpl::size_type size, bool created) const
- {
- if(((m_type == DoOpen) && created) ||
- ((m_type == DoCreate) && !created))
+ bool operator()(void *addr, std::size_t size, bool created) const
+ {
+ if( ((m_type == DoOpen) && created) ||
+ ((m_type == DoCreate) && !created) ||
+ //Check for overflow
+ size_type(-1) < size ){
return false;
+ }
+ else if(created){
+ return m_frontend->create_impl(addr, static_cast<size_type>(size));
+ }
+ else{
+ return m_frontend->open_impl (addr, static_cast<size_type>(size));
+ }
+ }
- if(created)
- return m_frontend->create_impl(addr, size);
- else
- return m_frontend->open_impl (addr, size);
+ std::size_t get_min_size() const
+ {
+ const size_type sz = m_frontend->get_segment_manager()->get_min_size();
+ if(sz > std::size_t(-1)){
+ //The minimum size is not representable by std::size_t
+ BOOST_ASSERT(false);
+ return std::size_t(-1);
+ }
+ else{
+ return static_cast<std::size_t>(sz);
+ }
}
private:
diff --git a/boost/interprocess/detail/managed_multi_shared_memory.hpp b/boost/interprocess/detail/managed_multi_shared_memory.hpp
index 654c8bb9f3..4c2ef14dcc 100644
--- a/boost/interprocess/detail/managed_multi_shared_memory.hpp
+++ b/boost/interprocess/detail/managed_multi_shared_memory.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
#define BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -36,7 +36,7 @@
#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/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>
//!\file
@@ -69,10 +69,10 @@ class 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;
+ managed_open_or_create_impl<shared_memory_object, MemoryAlgorithm::Alignment, true, false> managed_impl;
typedef typename void_pointer::segment_group_id segment_group_id;
typedef typename base_t::size_type size_type;
@@ -100,7 +100,7 @@ class basic_managed_multi_shared_memory
// 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;
@@ -134,7 +134,7 @@ class basic_managed_multi_shared_memory
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);
+ return result_type(static_cast<void *>(0), 0);
}
virtual bool update_segments ()
@@ -174,7 +174,7 @@ class basic_managed_multi_shared_memory
: 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;
@@ -211,9 +211,23 @@ class basic_managed_multi_shared_memory
}
return false;
}
+
+ std::size_t get_min_size() const
+ {
+ const size_type sz = mp_frontend->get_segment_manager()->get_min_size();
+ if(sz > std::size_t(-1)){
+ //The minimum size is not representable by std::size_t
+ BOOST_ASSERT(false);
+ return std::size_t(-1);
+ }
+ else{
+ return static_cast<std::size_t>(sz);
+ }
+ }
+
self_t * const mp_frontend;
type_t m_type;
- size_type m_segment_number;
+ size_type m_segment_number;
};
//!Functor to execute atomically when closing a shared memory segment.
@@ -226,7 +240,7 @@ class basic_managed_multi_shared_memory
: mp_frontend(frontend){}
void operator()(const mapped_region &region, bool last) const
- {
+ {
if(last) mp_frontend->destroy_impl();
else mp_frontend->close_impl();
}
@@ -251,7 +265,7 @@ class basic_managed_multi_shared_memory
const permissions &perm = permissions())
: m_group_services(get_this_pointer())
{
- priv_open_or_create(create_open_func::DoCreate,name, size, perm);
+ priv_open_or_create(create_open_func::DoCreate,name, size, perm);
}
basic_managed_multi_shared_memory(open_or_create_t,
@@ -301,7 +315,7 @@ class basic_managed_multi_shared_memory
if(group){
void_pointer::delete_group(group);
}
- return false;
+ return false;
}
bool priv_new_segment(typename create_open_func::type_t type,
@@ -368,7 +382,7 @@ class basic_managed_multi_shared_memory
//!Frees resources. Never throws.
void priv_close()
- {
+ {
if(!m_shmem_list.empty()){
bool ret;
//Obtain group identifier
@@ -385,7 +399,7 @@ class basic_managed_multi_shared_memory
m_shmem_list.clear();
}
}
-
+
private:
shmem_list_t m_shmem_list;
group_services m_group_services;
diff --git a/boost/interprocess/detail/managed_open_or_create_impl.hpp b/boost/interprocess/detail/managed_open_or_create_impl.hpp
index a4f1f15817..bd08be56d3 100644
--- a/boost/interprocess/detail/managed_open_or_create_impl.hpp
+++ b/boost/interprocess/detail/managed_open_or_create_impl.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
#define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
@@ -25,13 +29,14 @@
#include <boost/interprocess/permissions.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/interprocess/sync/spin/wait.hpp>
#include <boost/move/move.hpp>
#include <boost/cstdint.hpp>
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail{ class interprocess_tester; }
@@ -48,13 +53,13 @@ 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
+
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
namespace ipcdetail {
@@ -79,12 +84,12 @@ class managed_open_or_create_impl_device_holder<true, DeviceAbstraction>
const DeviceAbstraction &get_device() const
{ return dev; }
-
+
private:
DeviceAbstraction dev;
};
-template<class DeviceAbstraction, std::size_t MemAlignment = 0, bool FileBased = true, bool StoreDevice = true>
+template<class DeviceAbstraction, std::size_t MemAlignment, bool FileBased, bool StoreDevice>
class managed_open_or_create_impl
: public managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction>
{
@@ -94,9 +99,9 @@ class 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,
+ {
+ UninitializedSegment,
+ InitializingSegment,
InitializedSegment,
CorruptedSegment
};
@@ -222,10 +227,10 @@ class managed_open_or_create_impl
{ 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;
+ return *this;
}
~managed_open_or_create_impl()
@@ -309,14 +314,18 @@ class managed_open_or_create_impl
{
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));
+ if(type != DoOpen){
+ //Check if the requested size is enough to build the managed metadata
+ const std::size_t func_min_size = construct_func.get_min_size();
+ if( (std::size_t(-1) - ManagedOpenOrCreateUserOffset) < func_min_size ||
+ size < (func_min_size + ManagedOpenOrCreateUserOffset) ){
+ throw interprocess_exception(error_info(size_error));
+ }
}
//Check size can be represented by offset_t (used by truncate)
if(type != DoOpen && !check_offset_t_size<FileBased>(size, file_like_t())){
@@ -349,6 +358,7 @@ class managed_open_or_create_impl
//file and know if we have really created it or just open it
//drop me a e-mail!
bool completed = false;
+ spin_wait swait;
while(!completed){
try{
create_device<FileBased>(dev, id, size, perm, file_like_t());
@@ -366,8 +376,8 @@ class managed_open_or_create_impl
created = false;
completed = true;
}
- catch(interprocess_exception &ex){
- if(ex.get_error_code() != not_found_error){
+ catch(interprocess_exception &e){
+ if(e.get_error_code() != not_found_error){
throw;
}
}
@@ -379,7 +389,7 @@ class managed_open_or_create_impl
catch(...){
throw;
}
- thread_yield();
+ swait.yield();
}
}
@@ -426,11 +436,13 @@ class managed_open_or_create_impl
else{
if(FileBased){
offset_t filesize = 0;
+ spin_wait swait;
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()));
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
}
- thread_yield();
+ swait.yield();
}
if(filesize == 1){
throw interprocess_exception(error_info(corrupted_error));
@@ -442,8 +454,9 @@ class managed_open_or_create_impl
boost::uint32_t *patomic_word = static_cast<boost::uint32_t*>(region.get_address());
boost::uint32_t value = atomic_read32(patomic_word);
+ spin_wait swait;
while(value == InitializingSegment || value == UninitializedSegment){
- thread_yield();
+ swait.yield();
value = atomic_read32(patomic_word);
}
@@ -461,6 +474,11 @@ class managed_open_or_create_impl
}
}
+ friend void swap(managed_open_or_create_impl &left, managed_open_or_create_impl &right)
+ {
+ left.swap(right);
+ }
+
private:
friend class interprocess_tester;
void dont_close_on_destruction()
@@ -469,11 +487,6 @@ class managed_open_or_create_impl
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 {
diff --git a/boost/interprocess/detail/math_functions.hpp b/boost/interprocess/detail/math_functions.hpp
index 2fc457c683..3826f161e2 100644
--- a/boost/interprocess/detail/math_functions.hpp
+++ b/boost/interprocess/detail/math_functions.hpp
@@ -1,7 +1,7 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Stephen Cleary 2000.
-// (C) Copyright Ion Gaztanaga 2007-2011.
+// (C) Copyright Ion Gaztanaga 2007-2012.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -16,6 +16,10 @@
#ifndef BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP
#define BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <climits>
#include <boost/static_assert.hpp>
@@ -93,7 +97,7 @@ inline std::size_t floor_log2 (std::size_t x)
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)
diff --git a/boost/interprocess/detail/min_max.hpp b/boost/interprocess/detail/min_max.hpp
index 1f4ebdfc33..a5d01f404b 100644
--- a/boost/interprocess/detail/min_max.hpp
+++ b/boost/interprocess/detail/min_max.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011.
+// (C) Copyright Ion Gaztanaga 2005-2012.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,7 +13,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
#define BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/detail/move.hpp b/boost/interprocess/detail/move.hpp
index 1ec43b211b..22df7bd771 100644
--- a/boost/interprocess/detail/move.hpp
+++ b/boost/interprocess/detail/move.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2010-2011.
+// (C) Copyright Ion Gaztanaga 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -14,7 +14,11 @@
#ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP
#define BOOST_INTERPROCESS_DETAIL_MOVE_HPP
-#include <boost/move/move.hpp>
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/move/utility_core.hpp>
namespace boost {
namespace interprocess {
diff --git a/boost/interprocess/detail/mpl.hpp b/boost/interprocess/detail/mpl.hpp
index e2c7f52d24..29f3893038 100644
--- a/boost/interprocess/detail/mpl.hpp
+++ b/boost/interprocess/detail/mpl.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011.
+// (C) Copyright Ion Gaztanaga 2005-2012.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,7 +13,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP
#define BOOST_INTERPROCESS_DETAIL_MPL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/detail/multi_segment_services.hpp b/boost/interprocess/detail/multi_segment_services.hpp
index d1451d3379..dd9d5f82fd 100644
--- a/boost/interprocess/detail/multi_segment_services.hpp
+++ b/boost/interprocess/detail/multi_segment_services.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP
#define BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/detail/named_proxy.hpp b/boost/interprocess/detail/named_proxy.hpp
index c2aafed9ac..ee6668c2d5 100644
--- a/boost/interprocess/detail/named_proxy.hpp
+++ b/boost/interprocess/detail/named_proxy.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
#define BOOST_INTERPROCESS_NAMED_PROXY_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -26,7 +26,7 @@
#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
#include <boost/interprocess/detail/preprocessor.hpp>
#else
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/detail/variadic_templates_tools.hpp>
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
@@ -93,7 +93,7 @@ struct CtorNArg : public placement_destroy<T>
{}
tuple<Args&...> args_;
-};
+};
//!Describes a proxy class that implements named
//!allocation syntax.
@@ -119,7 +119,7 @@ class named_proxy
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
@@ -199,7 +199,7 @@ struct Ctor0Arg : public placement_destroy<T>
// 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); }
//
@@ -293,7 +293,7 @@ class named_proxy
//!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);
diff --git a/boost/interprocess/detail/os_file_functions.hpp b/boost/interprocess/detail/os_file_functions.hpp
index 08decd9bc4..1b54807ab1 100644
--- a/boost/interprocess/detail/os_file_functions.hpp
+++ b/boost/interprocess/detail/os_file_functions.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
#define BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/errors.hpp>
@@ -19,8 +23,9 @@
#include <string>
#include <limits>
#include <climits>
+#include <boost/type_traits/make_unsigned.hpp>
-#if (defined BOOST_INTERPROCESS_WINDOWS)
+#if defined (BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
@@ -45,7 +50,7 @@
namespace boost {
namespace interprocess {
-#if (defined BOOST_INTERPROCESS_WINDOWS)
+#if defined (BOOST_INTERPROCESS_WINDOWS)
typedef void * file_handle_t;
typedef long long offset_t;
@@ -66,6 +71,9 @@ typedef enum { file_begin = winapi::file_begin
, file_current = winapi::file_current
} file_pos_t;
+typedef unsigned long map_options_t;
+static const map_options_t default_map_options = map_options_t(-1);
+
namespace ipcdetail{
inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
@@ -90,34 +98,47 @@ inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
inline bool create_directory(const char *path)
{ return winapi::create_directory(path); }
-inline const char *get_temporary_path()
-{ return std::getenv("TMP"); }
-
+inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len)
+{
+ required_len = 0;
+ //std::size_t is always bigger or equal than unsigned long in Windows systems
+ //In case std::size_t is bigger than unsigned long
+ unsigned long buf = buf_len;
+ if(buf_len != buf){ //maybe overflowed
+ return false;
+ }
+ required_len = winapi::get_temp_path(buf_len, buffer);
+ const bool ret = !(buf_len < required_len);
+ if(ret && buffer[required_len-1] == '\\'){
+ buffer[required_len-1] = 0;
+ }
+ return ret;
+}
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());
+ , (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());
+ , (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);
+ (name, (unsigned int)mode, winapi::open_existing, attr, 0);
}
inline bool delete_file(const char *name)
@@ -129,10 +150,10 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size)
if(!winapi::get_file_size(hnd, filesize))
return false;
- const offset_t max_filesize = (std::numeric_limits<offset_t>::max)();
+ typedef boost::make_unsigned<offset_t>::type uoffset_t;
+ const uoffset_t max_filesize = uoffset_t((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) ){
+ if(uoffset_t(size) > max_filesize){
winapi::set_last_error(winapi::error_file_too_large);
return false;
}
@@ -177,7 +198,7 @@ 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);
}
@@ -189,9 +210,9 @@ 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 = ~((unsigned long)(0u));
+ const unsigned long len = ((unsigned long)-1);
// winapi::interprocess_overlapped overlapped;
// std::memset(&overlapped, 0, sizeof(overlapped));
return winapi::lock_file_ex
@@ -199,8 +220,8 @@ inline bool acquire_file_lock(file_handle_t hnd)
}
inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
-{
- const unsigned long len = ~((unsigned long)(0u));
+{
+ const unsigned long len = ((unsigned long)-1);
winapi::interprocess_overlapped overlapped;
std::memset(&overlapped, 0, sizeof(overlapped));
if(!winapi::lock_file_ex
@@ -208,30 +229,30 @@ inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
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 = ~((unsigned long)(0u));
+{
+ const unsigned long len = ((unsigned long)-1);
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 = ~((unsigned long)(0u));
+{
+ const unsigned long len = ((unsigned long)-1);
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 = ~((unsigned long)(0u));
+{
+ const unsigned long len = ((unsigned long)-1);
winapi::interprocess_overlapped overlapped;
std::memset(&overlapped, 0, sizeof(overlapped));
if(!winapi::lock_file_ex
@@ -253,7 +274,7 @@ inline bool delete_subdirectories_recursive
void * hFile; // Handle to directory
std::string strFilePath; // Filepath
std::string strPattern; // Pattern
- winapi::win32_find_data_t FileInformation; // File information
+ winapi::win32_find_data FileInformation; // File information
//Find all files and directories
strPattern = refcstrRootDirectory + "\\*.*";
@@ -269,8 +290,10 @@ inline bool delete_subdirectories_recursive
//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))
+ if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1)){
+ winapi::find_close(hFile);
return false;
+ }
}
//If it's a file, just delete it
else{
@@ -278,7 +301,7 @@ inline bool delete_subdirectories_recursive
//if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0)
//return winapi::get_last_error();
// Delete file
- winapi::delete_file(strFilePath.c_str());
+ winapi::unlink_file(strFilePath.c_str());
}
}
//Go to the next file
@@ -319,7 +342,7 @@ template<class Function>
inline bool for_each_file_in_dir(const char *dir, Function f)
{
void * hFile; // Handle to directory
- winapi::win32_find_data_t FileInformation; // File information
+ winapi::win32_find_data FileInformation; // File information
//Get base directory
std::string str(dir);
@@ -352,7 +375,7 @@ inline bool for_each_file_in_dir(const char *dir, Function f)
}
-#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
+#else //#if defined (BOOST_INTERPROCESS_WINDOWS)
typedef int file_handle_t;
typedef off_t offset_t;
@@ -375,6 +398,9 @@ typedef enum { file_begin = SEEK_SET
, file_current = SEEK_CUR
} file_pos_t;
+typedef int map_options_t;
+static const map_options_t default_map_options = map_options_t(-1);
+
namespace ipcdetail{
inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
@@ -391,22 +417,20 @@ inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
inline bool create_directory(const char *path)
{ return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; }
-inline const char *get_temporary_path()
+inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len)
{
- 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];
- }
+ required_len = 5u;
+ if(buf_len < required_len)
+ return false;
+ else{
+ std::strcpy(buffer, "/tmp");
}
- return "/tmp";
+ return true;
}
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){
@@ -433,13 +457,16 @@ inline file_handle_t create_or_open_file
break;
}
}
+ else{
+ 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);
}
@@ -449,17 +476,16 @@ inline bool delete_file(const char *name)
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;
- }
+ typedef boost::make_unsigned<off_t>::type uoff_t;
+ if(uoff_t((std::numeric_limits<off_t>::max)()) < size){
+ 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){
@@ -472,7 +498,7 @@ 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);
}
@@ -522,7 +548,7 @@ inline bool release_file_lock(file_handle_t hnd)
}
inline bool acquire_file_lock_sharable(file_handle_t hnd)
-{
+{
struct ::flock lock;
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
@@ -532,7 +558,7 @@ inline bool acquire_file_lock_sharable(file_handle_t hnd)
}
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;
@@ -601,7 +627,7 @@ inline bool delete_subdirectories_recursive
|| (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
continue;
}
- if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){
+ if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){
continue;
}
fn = refcstrRootDirectory;
@@ -672,7 +698,7 @@ inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const
return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this );
}
-#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
+#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
inline bool open_or_create_directory(const char *dir_name)
{
@@ -686,6 +712,18 @@ inline bool open_or_create_directory(const char *dir_name)
return true;
}
+inline std::string get_temporary_path()
+{
+ std::size_t required_len = 0;
+ get_temporary_path(0, 0, required_len);
+ std::string ret_str(required_len, char(0));
+ get_temporary_path(&ret_str[0], ret_str.size(), required_len);
+ while(!ret_str.empty() && !ret_str[ret_str.size()-1]){
+ ret_str.erase(ret_str.size()-1);
+ }
+
+ return ret_str;
+}
} //namespace ipcdetail{
} //namespace interprocess {
diff --git a/boost/interprocess/detail/os_thread_functions.hpp b/boost/interprocess/detail/os_thread_functions.hpp
index 8d769fc4e9..4604683645 100644
--- a/boost/interprocess/detail/os_thread_functions.hpp
+++ b/boost/interprocess/detail/os_thread_functions.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -8,24 +8,60 @@
//
//////////////////////////////////////////////////////////////////////////////
+//Thread launching functions are adapted from boost/detail/lightweight_thread.hpp
+//
+// boost/detail/lightweight_thread.hpp
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2008 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
#ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
#define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/streams/bufferstream.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <cstddef>
+#include <memory>
-#if (defined BOOST_INTERPROCESS_WINDOWS)
+#if defined(BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
+# include <process.h>
#else
-# ifdef BOOST_HAS_UNISTD_H
-# include <pthread.h>
-# include <unistd.h>
-# include <sched.h>
-# include <time.h>
+# include <pthread.h>
+# include <unistd.h>
+# include <sched.h>
+# include <time.h>
+# ifdef BOOST_INTERPROCESS_BSD_DERIVATIVE
+ //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas
+ //others (FreeBSD & Darwin) need sys/types.h
+# include <sys/types.h>
+# include <sys/param.h>
+# include <sys/sysctl.h>
+# endif
+//According to the article "C/C++ tip: How to measure elapsed real time for benchmarking"
+# if defined(CLOCK_MONOTONIC_PRECISE) //BSD
+# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
+# elif defined(CLOCK_MONOTONIC_RAW) //Linux
+# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
+# elif defined(CLOCK_HIGHRES) //Solaris
+# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES
+# elif defined(CLOCK_MONOTONIC) //POSIX (AIX, BSD, Linux, Solaris)
+# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC
+# elif !defined(CLOCK_MONOTONIC) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
+# include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
+# define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
# else
-# error Unknown platform
+# error "No high resolution steady clock in your system, please provide a patch"
# endif
#endif
@@ -33,10 +69,11 @@ namespace boost {
namespace interprocess {
namespace ipcdetail{
-#if (defined BOOST_INTERPROCESS_WINDOWS)
+#if defined (BOOST_INTERPROCESS_WINDOWS)
typedef unsigned long OS_process_id_t;
typedef unsigned long OS_thread_id_t;
+typedef void* OS_thread_t;
typedef OS_thread_id_t OS_systemwide_thread_id_t;
//process
@@ -56,11 +93,83 @@ inline OS_thread_id_t get_invalid_thread_id()
inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
{ return id1 == id2; }
+//return the system tick in ns
+inline unsigned long get_system_tick_ns()
+{
+ unsigned long curres;
+ winapi::set_timer_resolution(10000, 0, &curres);
+ //Windows API returns the value in hundreds of ns
+ return (curres - 1ul)*100ul;
+}
+
+//return the system tick in us
+inline unsigned long get_system_tick_us()
+{
+ unsigned long curres;
+ winapi::set_timer_resolution(10000, 0, &curres);
+ //Windows API returns the value in hundreds of ns
+ return (curres - 1ul)/10ul + 1ul;
+}
+
+typedef unsigned __int64 OS_highres_count_t;
+
+inline unsigned long get_system_tick_in_highres_counts()
+{
+ __int64 freq;
+ unsigned long curres;
+ winapi::set_timer_resolution(10000, 0, &curres);
+ //Frequency in counts per second
+ if(!winapi::query_performance_frequency(&freq)){
+ //Tick resolution in ms
+ return (curres-1ul)/10000ul + 1ul;
+ }
+ else{
+ //In femtoseconds
+ __int64 count_fs = (1000000000000000LL - 1LL)/freq + 1LL;
+ __int64 tick_counts = (static_cast<__int64>(curres)*100000000LL - 1LL)/count_fs + 1LL;
+ return static_cast<unsigned long>(tick_counts);
+ }
+}
+
+inline OS_highres_count_t get_current_system_highres_count()
+{
+ __int64 count;
+ if(!winapi::query_performance_counter(&count)){
+ count = winapi::get_tick_count();
+ }
+ return count;
+}
+
+inline void zero_highres_count(OS_highres_count_t &count)
+{ count = 0; }
+
+inline bool is_highres_count_zero(const OS_highres_count_t &count)
+{ return count == 0; }
+
+template <class Ostream>
+inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
+{
+ ostream << count;
+ return ostream;
+}
+
+inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
+{ return l - r; }
+
+inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
+{ return l < r; }
+
+inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
+{ return l < static_cast<OS_highres_count_t>(r); }
+
+inline void thread_sleep_tick()
+{ winapi::sleep_tick(); }
+
inline void thread_yield()
{ winapi::sched_yield(); }
inline void thread_sleep(unsigned int ms)
-{ winapi::Sleep(ms); }
+{ winapi::sleep(ms); }
//systemwide thread
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
@@ -88,7 +197,7 @@ inline long double get_current_process_creation_time()
{
winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime;
- get_process_times
+ winapi::get_process_times
( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
typedef long double ldouble_t;
@@ -97,14 +206,22 @@ inline long double get_current_process_creation_time()
CreationTime.dwLowDateTime*resolution;
}
+inline unsigned int get_num_cores()
+{
+ winapi::system_info sysinfo;
+ winapi::get_system_info( &sysinfo );
+ //in Windows dw is long which is equal in bits to int
+ return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
+}
-#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
+#else //#if defined (BOOST_INTERPROCESS_WINDOWS)
+typedef pthread_t OS_thread_t;
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()
{}
@@ -164,9 +281,135 @@ inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
inline void thread_yield()
{ ::sched_yield(); }
+#ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
+typedef struct timespec OS_highres_count_t;
+#else
+typedef unsigned long long OS_highres_count_t;
+#endif
+
+inline unsigned long get_system_tick_ns()
+{
+ #ifdef _SC_CLK_TCK
+ long ticks_per_second =::sysconf(_SC_CLK_TCK); // ticks per sec
+ if(ticks_per_second <= 0){ //Try a typical value on error
+ ticks_per_second = 100;
+ }
+ return 999999999ul/static_cast<unsigned long>(ticks_per_second)+1ul;
+ #else
+ #error "Can't obtain system tick value for your system, please provide a patch"
+ #endif
+}
+
+inline unsigned long get_system_tick_in_highres_counts()
+{
+ #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
+ return get_system_tick_ns();
+ #else
+ mach_timebase_info_data_t info;
+ mach_timebase_info(&info);
+ //ns
+ return static_cast<unsigned long>
+ (
+ static_cast<double>(get_system_tick_ns())
+ / (static_cast<double>(info.numer) / info.denom)
+ );
+ #endif
+}
+
+//return system ticks in us
+inline unsigned long get_system_tick_us()
+{
+ return (get_system_tick_ns()-1)/1000ul + 1ul;
+}
+
+inline OS_highres_count_t get_current_system_highres_count()
+{
+ #if defined(BOOST_INTERPROCESS_CLOCK_MONOTONIC)
+ struct timespec count;
+ ::clock_gettime(BOOST_INTERPROCESS_CLOCK_MONOTONIC, &count);
+ return count;
+ #elif defined(BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME)
+ return ::mach_absolute_time();
+ #endif
+}
+
+#ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
+
+inline void zero_highres_count(OS_highres_count_t &count)
+{ count.tv_sec = 0; count.tv_nsec = 0; }
+
+inline bool is_highres_count_zero(const OS_highres_count_t &count)
+{ return count.tv_sec == 0 && count.tv_nsec == 0; }
+
+template <class Ostream>
+inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
+{
+ ostream << count.tv_sec << "s:" << count.tv_nsec << "ns";
+ return ostream;
+}
+
+inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
+{
+ OS_highres_count_t res;
+
+ if (l.tv_nsec < r.tv_nsec){
+ res.tv_nsec = 1000000000 + l.tv_nsec - r.tv_nsec;
+ res.tv_sec = l.tv_sec - 1 - r.tv_sec;
+ }
+ else{
+ res.tv_nsec = l.tv_nsec - r.tv_nsec;
+ res.tv_sec = l.tv_sec - r.tv_sec;
+ }
+
+ return res;
+}
+
+inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
+{ return l.tv_sec < r.tv_sec || (l.tv_sec == r.tv_sec && l.tv_nsec < r.tv_nsec); }
+
+inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
+{ return !l.tv_sec && (static_cast<unsigned long>(l.tv_nsec) < r); }
+
+#else
+
+inline void zero_highres_count(OS_highres_count_t &count)
+{ count = 0; }
+
+inline bool is_highres_count_zero(const OS_highres_count_t &count)
+{ return count == 0; }
+
+template <class Ostream>
+inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
+{
+ ostream << count ;
+ return ostream;
+}
+
+inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
+{ return l - r; }
+
+inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
+{ return l < r; }
+
+inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
+{ return l < static_cast<OS_highres_count_t>(r); }
+
+#endif
+
+inline void thread_sleep_tick()
+{
+ struct timespec rqt;
+ //Sleep for the half of the tick time
+ rqt.tv_sec = 0;
+ rqt.tv_nsec = get_system_tick_ns()/2;
+ ::nanosleep(&rqt, 0);
+}
+
inline void thread_sleep(unsigned int ms)
{
- const struct timespec rqt = { ms/1000u, (ms%1000u)*1000000u };
+ struct timespec rqt;
+ rqt.tv_sec = ms/1000u;
+ rqt.tv_nsec = (ms%1000u)*1000000u;
::nanosleep(&rqt, 0);
}
@@ -189,7 +432,46 @@ inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
inline long double get_current_process_creation_time()
{ return 0.0L; }
-#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
+inline unsigned int get_num_cores()
+{
+ #ifdef _SC_NPROCESSORS_ONLN
+ long cores = ::sysconf(_SC_NPROCESSORS_ONLN);
+ // sysconf returns -1 if the name is invalid, the option does not exist or
+ // does not have a definite limit.
+ // if sysconf returns some other negative number, we have no idea
+ // what is going on. Default to something safe.
+ if(cores <= 0){
+ return 1;
+ }
+ //Check for overflow (unlikely)
+ else if(static_cast<unsigned long>(cores) >=
+ static_cast<unsigned long>(static_cast<unsigned int>(-1))){
+ return static_cast<unsigned int>(-1);
+ }
+ else{
+ return static_cast<unsigned int>(cores);
+ }
+ #elif defined(BOOST_INTERPROCESS_BSD_DERIVATIVE) && defined(HW_NCPU)
+ int request[2] = { CTL_HW, HW_NCPU };
+ int num_cores;
+ std::size_t result_len = sizeof(num_cores);
+ if ( (::sysctl (request, 2, &num_cores, &result_len, 0, 0) < 0) || (num_cores <= 0) ){
+ //Return a safe value
+ return 1;
+ }
+ else{
+ return static_cast<unsigned int>(num_cores);
+ }
+ #endif
+}
+
+inline int thread_create(OS_thread_t * thread, void *(*start_routine)(void*), void* arg)
+{ return pthread_create(thread, 0, start_routine, arg); }
+
+inline void thread_join(OS_thread_t thread)
+{ (void)pthread_join(thread, 0); }
+
+#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
@@ -202,6 +484,111 @@ inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid)
inline void get_pid_str(pid_str_t &pid_str)
{ get_pid_str(pid_str, get_current_process_id()); }
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+
+inline int thread_create( OS_thread_t * thread, unsigned (__stdcall * start_routine) (void*), void* arg )
+{
+ void* h = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
+
+ if( h != 0 ){
+ *thread = h;
+ return 0;
+ }
+ else{
+ return 1;
+ }
+}
+
+inline void thread_join( OS_thread_t thread)
+{
+ winapi::wait_for_single_object( thread, winapi::infinite_time );
+ winapi::close_handle( thread );
+}
+
+#endif
+
+class abstract_thread
+{
+ public:
+ virtual ~abstract_thread() {}
+ virtual void run() = 0;
+};
+
+template<class T>
+class os_thread_func_ptr_deleter
+{
+ public:
+ explicit os_thread_func_ptr_deleter(T* p)
+ : m_p(p)
+ {}
+
+ T *release()
+ { T *p = m_p; m_p = 0; return p; }
+
+ T *get() const
+ { return m_p; }
+
+ T *operator ->() const
+ { return m_p; }
+
+ ~os_thread_func_ptr_deleter()
+ { delete m_p; }
+
+ private:
+ T *m_p;
+};
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+
+inline unsigned __stdcall launch_thread_routine( void * pv )
+{
+ os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
+ pt->run();
+ return 0;
+}
+
+#else
+
+extern "C" void * launch_thread_routine( void * pv );
+
+inline void * launch_thread_routine( void * pv )
+{
+ os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
+ pt->run();
+ return 0;
+}
+
+#endif
+
+template<class F>
+class launch_thread_impl
+ : public abstract_thread
+{
+ public:
+ explicit launch_thread_impl( F f )
+ : f_( f )
+ {}
+
+ void run()
+ { f_(); }
+
+ private:
+ F f_;
+};
+
+template<class F>
+inline int thread_launch( OS_thread_t & pt, F f )
+{
+ os_thread_func_ptr_deleter<abstract_thread> p( new launch_thread_impl<F>( f ) );
+
+ int r = thread_create(&pt, launch_thread_routine, p.get());
+ if( r == 0 ){
+ p.release();
+ }
+
+ return r;
+}
+
} //namespace ipcdetail{
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/detail/pointer_type.hpp b/boost/interprocess/detail/pointer_type.hpp
index 549b23fa6c..28b053c2ae 100644
--- a/boost/interprocess/detail/pointer_type.hpp
+++ b/boost/interprocess/detail/pointer_type.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011.
+// (C) Copyright Ion Gaztanaga 2005-2012.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
@@ -14,7 +14,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP
#define BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/detail/portable_intermodule_singleton.hpp b/boost/interprocess/detail/portable_intermodule_singleton.hpp
index eb2a13e104..80897f2721 100644
--- a/boost/interprocess/detail/portable_intermodule_singleton.hpp
+++ b/boost/interprocess/detail/portable_intermodule_singleton.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP
#define BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP
-#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#if defined(_MSC_VER)
#pragma once
#endif
@@ -23,7 +23,7 @@
#include <boost/interprocess/shared_memory_object.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/shared_dir_helpers.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/detail/file_locking_helpers.hpp>
#include <boost/assert.hpp>
@@ -45,16 +45,17 @@ static void create_tmp_subdir_and_get_pid_based_filepath
{
//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);
+ create_shared_dir_and_clean_old(s);
s += "/";
s += subdir_name;
if(!open_or_create_directory(s.c_str())){
- throw interprocess_exception(error_info(system_error_code()));
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
}
s += "/";
s += file_prefix;
if(creation_time){
- std::string sstamp;
+ std::string sstamp;
get_pid_creation_time_str(sstamp);
s += sstamp;
}
@@ -137,7 +138,7 @@ struct thread_safe_global_map_dependant<managed_global_memory>
delete_file(singleton_lock_file_path_);
shared_memory_object::remove(shm_name_);
}
-
+
const char * const shm_name_;
const char * const singleton_lock_file_path_;
managed_global_memory & shm_;
@@ -187,7 +188,7 @@ struct thread_safe_global_map_dependant<managed_global_memory>
static bool remove_old_gmem()
{
std::string refcstrRootDirectory;
- tmp_folder(refcstrRootDirectory);
+ get_shared_dir(refcstrRootDirectory);
refcstrRootDirectory += "/";
refcstrRootDirectory += get_lock_file_subdir_name();
return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic);
@@ -222,11 +223,11 @@ struct thread_safe_global_map_dependant<managed_global_memory>
//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 = open_or_create_and_lock_file(lck_str.c_str());
+ int fd_lockfile = open_or_create_and_lock_file(lck_str.c_str());
//If failed, write a bad file descriptor to notify other modules that
//something was wrong and unlink shared memory. Mark the function object
//to tell caller to retry with another shared memory
- if(fd < 0){
+ if(fd_lockfile < 0){
this->register_lock_file(GMemMarkToBeRemoved);
std::string s;
get_map_name(s);
@@ -235,7 +236,7 @@ struct thread_safe_global_map_dependant<managed_global_memory>
}
//If successful, register the file descriptor
else{
- this->register_lock_file(fd);
+ this->register_lock_file(fd_lockfile);
}
}
//If the fd was invalid (maybe a previous try failed) notify caller that
@@ -342,7 +343,7 @@ struct thread_safe_global_map_dependant<managed_global_memory>
} //namespace intermodule_singleton_helpers {
-template<typename C, bool LazyInit = true, bool Phoenix = true>
+template<typename C, bool LazyInit = true, bool Phoenix = false>
class portable_intermodule_singleton
: public intermodule_singleton_impl<C, LazyInit, Phoenix, managed_global_memory>
{};
diff --git a/boost/interprocess/detail/posix_time_types_wrk.hpp b/boost/interprocess/detail/posix_time_types_wrk.hpp
index e4df85a572..dbde3d1771 100644
--- a/boost/interprocess/detail/posix_time_types_wrk.hpp
+++ b/boost/interprocess/detail/posix_time_types_wrk.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
#define BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
//workaround to avoid winsock redefines when using date-time
#ifdef _WIN32
diff --git a/boost/interprocess/detail/preprocessor.hpp b/boost/interprocess/detail/preprocessor.hpp
index 47b591c901..06d1354ee1 100644
--- a/boost/interprocess/detail/preprocessor.hpp
+++ b/boost/interprocess/detail/preprocessor.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
#define BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -35,7 +35,7 @@
//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
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
//!
@@ -45,7 +45,7 @@
//!
#endif
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_INTERPROCESS_PP_PARAM(U, u) \
U && u \
//!
@@ -55,80 +55,144 @@
//!
#endif
-#ifndef BOOST_NO_RVALUE_REFERENCES
-
- #if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
-
- #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
- BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
- //!
-
-
- #else //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \
//!
- #endif //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
-
-#else //#ifndef BOOST_NO_RVALUE_REFERENCES
+#else //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#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
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+ #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); \
-//!
+ namespace boost {
+ namespace interprocess {
+ namespace ipcdetail {
+ template<class T>
+ struct ref_holder;
+
+ template<class T>
+ struct ref_holder<T &>
+ {
+ ref_holder(T &t)
+ : t_(t)
+ {}
+ T &t_;
+ T & get() { return t_; }
+ T & get_lvalue() { return t_; }
+ };
+
+ template<class T>
+ struct ref_holder<const T>
+ {
+ ref_holder(const T &t)
+ : t_(t)
+ {}
+ const T &t_;
+ const T & get() { return t_; }
+ const T & get_lvalue() { return t_; }
+ };
+
+ template<class T>
+ struct ref_holder<const T &&>
+ {
+ ref_holder(const T &t)
+ : t_(t)
+ {}
+ const T &t_;
+ const T & get() { return t_; }
+ const T & get_lvalue() { return t_; }
+ };
+
+ template<class T>
+ struct ref_holder
+ {
+ ref_holder(T &&t)
+ : t_(t)
+ {}
+ T &t_;
+ T && get() { return ::boost::move(t_); }
+ T & get_lvalue() { return t_; }
+ };
+
+ template<class T>
+ struct ref_holder<T &&>
+ {
+ ref_holder(T &&t)
+ : t(t)
+ {}
+ T &t;
+ T && get() { return ::boost::move(t_); }
+ T & get_lvalue() { return t_; }
+ };
+
+ } //namespace ipcdetail {
+ } //namespace interprocess {
+ } //namespace boost {
+
+ #define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \
+ ::boost::interprocess::ipcdetail::ref_holder<BOOST_PP_CAT(P, n)> BOOST_PP_CAT(m_p, n); \
+ //!
+
+ #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \
+ BOOST_PP_CAT(++m_p, n).get_lvalue() \
+ //!
+
+ #else //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); \
+ //!
+
+ #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \
+ 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); \
+ //!
-#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)
-
+ #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \
+ 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
#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)
+#if !defined(BOOST_NO_CXX11_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_PP_CAT(this->m_p, n).get() \
+ //!
-#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) ) \
-//!
+ #define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \
+ BOOST_PP_CAT(*m_p, n).get_lvalue() \
+ //!
#else
-#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
-::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
-//!
+ #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) \
+ //!
-#define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \
-BOOST_PP_CAT(*m_p, n) \
-//!
+
+#endif //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#include <boost/interprocess/detail/config_end.hpp>
diff --git a/boost/interprocess/detail/ptime_wrk.hpp b/boost/interprocess/detail/ptime_wrk.hpp
index 8cda3a445d..87f05e25c2 100644
--- a/boost/interprocess/detail/ptime_wrk.hpp
+++ b/boost/interprocess/detail/ptime_wrk.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP
#define BOOST_INTERPROCESS_PTIME_WRK_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
//workaround to avoid winsock redefines when using date-time
#ifdef _WIN32
diff --git a/boost/interprocess/detail/robust_emulation.hpp b/boost/interprocess/detail/robust_emulation.hpp
index 1feb42dc35..d586db5071 100644
--- a/boost/interprocess/detail/robust_emulation.hpp
+++ b/boost/interprocess/detail/robust_emulation.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2010-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2010-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_ROBUST_EMULATION_HPP
#define BOOST_INTERPROCESS_ROBUST_EMULATION_HPP
-#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#if defined(_MSC_VER)
#pragma once
#endif
@@ -21,9 +21,12 @@
#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/shared_dir_helpers.hpp>
#include <boost/interprocess/detail/intermodule_singleton.hpp>
+#include <boost/interprocess/detail/portable_intermodule_singleton.hpp>
#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/sync/spin/wait.hpp>
+#include <boost/interprocess/sync/detail/common_algorithms.hpp>
#include <string>
namespace boost{
@@ -61,7 +64,7 @@ inline const char *robust_lock_prefix()
inline void robust_lock_path(std::string &s)
{
- tmp_folder(s);
+ get_shared_dir(s);
s += "/";
s += robust_lock_subdir_path();
}
@@ -132,7 +135,7 @@ class robust_mutex_lock_file
throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: create_file filed with unexpected error");
}
}
- }
+ }
~robust_mutex_lock_file()
{
@@ -197,8 +200,8 @@ class robust_spin_mutex
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);
+ bool is_owner_dead(boost::uint32_t own);
+ void owner_to_filename(boost::uint32_t own, std::string &s);
//The real mutex
Mutex mtx;
//The pid of the owner
@@ -214,42 +217,7 @@ inline robust_spin_mutex<Mutex>::robust_spin_mutex()
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;
- }
- }
- }
- }
-}
+{ try_based_lock(*this); }
template<class Mutex>
inline bool robust_spin_mutex<Mutex>::try_lock()
@@ -280,38 +248,12 @@ inline bool robust_spin_mutex<Mutex>::try_lock()
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;
-}
+{ return try_based_timed_lock(*this, abs_time); }
template<class Mutex>
-inline void robust_spin_mutex<Mutex>::owner_to_filename(boost::uint32_t owner, std::string &s)
+inline void robust_spin_mutex<Mutex>::owner_to_filename(boost::uint32_t own, std::string &s)
{
- robust_emulation_helpers::create_and_get_robust_lock_file_path(s, owner);
+ robust_emulation_helpers::create_and_get_robust_lock_file_path(s, own);
}
template<class Mutex>
@@ -324,7 +266,7 @@ inline bool robust_spin_mutex<Mutex>::robust_check()
return false;
}
atomic_write32(&this->state, fixing_state);
- return true;
+ return true;
}
template<class Mutex>
@@ -349,16 +291,16 @@ inline bool robust_spin_mutex<Mutex>::check_if_owner_dead_and_take_ownership_ato
}
template<class Mutex>
-inline bool robust_spin_mutex<Mutex>::is_owner_dead(boost::uint32_t owner)
+inline bool robust_spin_mutex<Mutex>::is_owner_dead(boost::uint32_t own)
{
//If owner is an invalid id, then it's clear it's dead
- if(owner == (boost::uint32_t)get_invalid_process_id()){
+ if(own == (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);
+ this->owner_to_filename(own, file);
//Now the logic is to open and lock it
file_handle_t fhnd = open_existing_file(file.c_str(), read_write);
@@ -404,7 +346,7 @@ 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()
diff --git a/boost/interprocess/detail/segment_manager_helper.hpp b/boost/interprocess/detail/segment_manager_helper.hpp
index 2b715d8f5e..1809a8d91a 100644
--- a/boost/interprocess/detail/segment_manager_helper.hpp
+++ b/boost/interprocess/detail/segment_manager_helper.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
#define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -32,6 +32,7 @@
#include <string> //char_traits
#include <new> //std::nothrow
#include <utility> //std::pair
+#include <iterator> //std::iterator_traits
#include <boost/assert.hpp> //BOOST_ASSERT
#include <functional> //unary_function
#ifndef BOOST_NO_EXCEPTIONS
@@ -72,7 +73,6 @@ class mem_algo_deallocator
{ if(m_ptr) m_algo.deallocate(m_ptr); }
};
-/// @cond
template<class size_type>
struct block_header
{
@@ -81,21 +81,18 @@ struct block_header
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
+ block_header(size_type val_bytes
+ ,size_type val_alignment
+ ,unsigned char al_type
+ ,std::size_t szof_char
,std::size_t num_char
)
- : m_value_bytes(value_bytes)
+ : m_value_bytes(val_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) )
+ , m_value_alignment((unsigned char)val_alignment)
+ , m_alloc_type_sizeof_char( (al_type << 5u) | ((unsigned char)szof_char & 0x1F) )
{};
-
template<class T>
block_header &operator= (const T& )
{ return *this; }
@@ -118,7 +115,7 @@ struct block_header
{
return get_rounded_size
( size_type(sizeof(Header))
- , size_type(::boost::alignment_of<block_header<size_type> >::value))
+ , size_type(::boost::alignment_of<block_header<size_type> >::value))
+ total_size();
}
@@ -130,7 +127,7 @@ struct block_header
template<class CharType>
CharType *name() const
- {
+ {
return const_cast<CharType*>(reinterpret_cast<const CharType*>
(reinterpret_cast<const char*>(this) + name_offset()));
}
@@ -175,7 +172,7 @@ struct block_header
{ 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) -
@@ -189,20 +186,20 @@ struct block_header
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)));
+ 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)));
+ get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value)));
//Some sanity checks
return hdr;
}
@@ -326,6 +323,15 @@ class char_ptr_holder
operator const CharType *()
{ return m_name; }
+ const CharType *get() const
+ { return m_name; }
+
+ bool is_unique() const
+ { return m_name == reinterpret_cast<CharType*>(-1); }
+
+ bool is_anonymous() const
+ { return m_name == static_cast<CharType*>(0); }
+
private:
const CharType *m_name;
};
@@ -350,8 +356,9 @@ struct index_key
public:
//!Constructor of the key
- index_key (const char_type *name, size_type length)
- : mp_str(name), m_len(length) {}
+ index_key (const char_type *nm, size_type length)
+ : mp_str(nm), m_len(length)
+ {}
//!Less than function for index ordering
bool operator < (const index_key & right) const
@@ -372,8 +379,8 @@ struct index_key
to_raw_pointer(right.mp_str), m_len) == 0;
}
- void name(const CharT *name)
- { mp_str = name; }
+ void name(const CharT *nm)
+ { mp_str = nm; }
void name_length(size_type len)
{ m_len = len; }
@@ -474,12 +481,12 @@ class segment_manager_iterator_value_adaptor<Iterator, false>
template<class Iterator, bool intrusive>
struct segment_manager_iterator_transform
- : std::unary_function< typename Iterator::value_type
+ : std::unary_function< typename std::iterator_traits<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
+
+ result_type operator()(const typename std::iterator_traits<Iterator>::value_type &arg) const
{ return result_type(arg); }
};
diff --git a/boost/interprocess/detail/tmp_dir_helpers.hpp b/boost/interprocess/detail/shared_dir_helpers.hpp
index 28e7341406..469ea04ac1 100644
--- a/boost/interprocess/detail/tmp_dir_helpers.hpp
+++ b/boost/interprocess/detail/shared_dir_helpers.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2007-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -8,8 +8,12 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
-#define BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
+#ifndef BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP
+#define BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -33,7 +37,11 @@ namespace ipcdetail {
{
windows_bootstamp()
{
- winapi::get_last_bootup_time(stamp);
+ //Throw if bootstamp not available
+ if(!winapi::get_last_bootup_time(stamp)){
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
}
//Use std::string. Even if this will be constructed in shared memory, all
//modules/dlls are from this process so internal raw pointers to heap are always valid
@@ -58,7 +66,7 @@ namespace ipcdetail {
struct ::timeval result;
std::size_t result_len = sizeof result;
- if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0)
+ if (::sysctl (request, 2, &result, &result_len, 0, 0) < 0)
return;
char bootstamp_str[256];
@@ -90,78 +98,84 @@ namespace ipcdetail {
#endif
#endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
-inline void get_tmp_base_dir(std::string &tmp_name)
+inline void get_shared_dir_root(std::string &dir_path)
{
#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();
- }
+ winapi::get_shared_documents_folder(dir_path);
#else
- tmp_name = get_temporary_path();
+ dir_path = "/tmp";
#endif
- if(tmp_name.empty()){
+ //We always need this path, so throw on error
+ if(dir_path.empty()){
error_info err = system_error_code();
throw interprocess_exception(err);
}
//Remove final null.
- tmp_name += "/boost_interprocess";
+ dir_path += "/boost_interprocess";
}
-inline void tmp_folder(std::string &tmp_name)
+inline void get_shared_dir(std::string &shared_dir)
{
- get_tmp_base_dir(tmp_name);
- #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
- tmp_name += "/";
- get_bootstamp(tmp_name, true);
+ #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH)
+ shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH;
+ #else
+ get_shared_dir_root(shared_dir);
+ #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
+ shared_dir += "/";
+ get_bootstamp(shared_dir, true);
+ #endif
#endif
}
-inline void tmp_filename(const char *filename, std::string &tmp_name)
+inline void shared_filepath(const char *filename, std::string &filepath)
{
- tmp_folder(tmp_name);
- tmp_name += "/";
- tmp_name += filename;
+ get_shared_dir(filepath);
+ filepath += "/";
+ filepath += filename;
}
-inline void create_tmp_and_clean_old(std::string &tmp_name)
+inline void create_shared_dir_and_clean_old(std::string &shared_dir)
{
- //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);
- }
- }
-
- #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
- tmp_folder(tmp_name);
+ #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH)
+ shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH;
+ #else
+ //First get the temp directory
+ std::string root_shared_dir;
+ get_shared_dir_root(root_shared_dir);
//If fails, check that it's because already exists
- if(!create_directory(tmp_name.c_str())){
+ if(!create_directory(root_shared_dir.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;
+
+ #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
+ get_shared_dir(shared_dir);
+
+ //If fails, check that it's because already exists
+ if(!create_directory(shared_dir.c_str())){
+ 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 = shared_dir;
+ subdir.erase(0, root_shared_dir.size()+1);
+ delete_subdirectories(root_shared_dir, subdir.c_str());
+ #else
+ shared_dir = root_shared_dir;
+ #endif
#endif
}
-inline void create_tmp_and_clean_old_and_get_filename(const char *filename, std::string &tmp_name)
+inline void create_shared_dir_cleaning_old_and_get_filepath(const char *filename, std::string &shared_dir)
{
- create_tmp_and_clean_old(tmp_name);
- tmp_name += "/";
- tmp_name += filename;
+ create_shared_dir_and_clean_old(shared_dir);
+ shared_dir += "/";
+ shared_dir += filename;
}
inline void add_leading_slash(const char *name, std::string &new_name)
@@ -178,4 +192,4 @@ inline void add_leading_slash(const char *name, std::string &new_name)
#include <boost/interprocess/detail/config_end.hpp>
-#endif //ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
+#endif //ifndef BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP
diff --git a/boost/interprocess/detail/transform_iterator.hpp b/boost/interprocess/detail/transform_iterator.hpp
index 922c875d6d..5496d19568 100644
--- a/boost/interprocess/detail/transform_iterator.hpp
+++ b/boost/interprocess/detail/transform_iterator.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011.
+// (C) Copyright Ion Gaztanaga 2005-2012.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
@@ -14,7 +14,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
#define BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -61,9 +61,9 @@ template <class Iterator, class UnaryFunction>
class transform_iterator
: public UnaryFunction
, public std::iterator
- < typename Iterator::iterator_category
+ < typename std::iterator_traits<Iterator>::iterator_category
, typename ipcdetail::remove_reference<typename UnaryFunction::result_type>::type
- , typename Iterator::difference_type
+ , typename std::iterator_traits<Iterator>::difference_type
, operator_arrow_proxy<typename UnaryFunction::result_type>
, typename UnaryFunction::result_type>
{
@@ -115,33 +115,33 @@ class transform_iterator
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)
+ friend typename std::iterator_traits<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)
+ transform_iterator& operator+=(typename std::iterator_traits<Iterator>::difference_type off)
{ this->advance(off); return *this; }
- transform_iterator operator+(typename Iterator::difference_type off) const
+ transform_iterator operator+(typename std::iterator_traits<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)
+ friend transform_iterator operator+(typename std::iterator_traits<Iterator>::difference_type off, const transform_iterator& right)
{ return right + off; }
- transform_iterator& operator-=(typename Iterator::difference_type off)
+ transform_iterator& operator-=(typename std::iterator_traits<Iterator>::difference_type off)
{ this->advance(-off); return *this; }
- transform_iterator operator-(typename Iterator::difference_type off) const
+ transform_iterator operator-(typename std::iterator_traits<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
+ typename UnaryFunction::result_type operator[](typename std::iterator_traits<Iterator>::difference_type off) const
{ return UnaryFunction::operator()(m_it[off]); }
operator_arrow_proxy<typename UnaryFunction::result_type>
@@ -172,10 +172,10 @@ class transform_iterator
typename UnaryFunction::result_type dereference() const
{ return UnaryFunction::operator()(*m_it); }
- void advance(typename Iterator::difference_type n)
+ void advance(typename std::iterator_traits<Iterator>::difference_type n)
{ std::advance(m_it, n); }
- typename Iterator::difference_type distance_to(const transform_iterator &other)const
+ typename std::iterator_traits<Iterator>::difference_type distance_to(const transform_iterator &other)const
{ return std::distance(other.m_it, m_it); }
};
diff --git a/boost/interprocess/detail/type_traits.hpp b/boost/interprocess/detail/type_traits.hpp
index 7a582fee5c..e56a495754 100644
--- a/boost/interprocess/detail/type_traits.hpp
+++ b/boost/interprocess/detail/type_traits.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
// (C) Copyright John Maddock 2000.
-// (C) Copyright Ion Gaztanaga 2005-2011.
+// (C) Copyright Ion Gaztanaga 2005-2012.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,7 +13,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
#define BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -117,6 +117,12 @@ struct remove_volatile<volatile T>
typedef T type;
};
+template<class T>
+struct remove_const_volatile
+{
+ typedef typename remove_const<typename remove_volatile<T>::type>::type type;
+};
+
template <typename T, typename U>
struct is_same
{
@@ -136,6 +142,13 @@ struct is_same
static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u));
};
+template<class T, class U>
+struct is_cv_same
+{
+ static const bool value = is_same< typename remove_const_volatile<T>::type
+ , typename remove_const_volatile<U>::type >::value;
+};
+
} // namespace ipcdetail
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/detail/utilities.hpp b/boost/interprocess/detail/utilities.hpp
index fcb211fb09..351b76cce4 100644
--- a/boost/interprocess/detail/utilities.hpp
+++ b/boost/interprocess/detail/utilities.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011.
+// (C) Copyright Ion Gaztanaga 2005-2012.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
@@ -14,7 +14,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
#define BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -22,7 +22,7 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/interprocess/detail/min_max.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
@@ -30,9 +30,11 @@
#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 <boost/move/utility_core.hpp>
+#include <boost/static_assert.hpp>
#include <utility>
#include <algorithm>
+#include <climits>
namespace boost {
namespace interprocess {
@@ -86,7 +88,10 @@ inline SizeType get_truncated_size_po2(SizeType orig_size, SizeType multiple)
template <std::size_t OrigSize, std::size_t RoundTo>
struct ct_rounded_size
{
- static const std::size_t value = ((OrigSize-1)/RoundTo+1)*RoundTo;
+ BOOST_STATIC_ASSERT((RoundTo != 0));
+ static const std::size_t intermediate_value = (OrigSize-1)/RoundTo+1;
+ BOOST_STATIC_ASSERT(intermediate_value <= std::size_t(-1)/RoundTo);
+ static const std::size_t value = intermediate_value*RoundTo;
};
// Gennaro Prota wrote this. Thanks!
@@ -133,6 +138,61 @@ addressof(T& v)
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
+template<class SizeType>
+struct sqrt_size_type_max
+{
+ static const SizeType value = (SizeType(1) << (sizeof(SizeType)*(CHAR_BIT/2)))-1;
+};
+
+template<class SizeType>
+inline bool multiplication_overflows(SizeType a, SizeType b)
+{
+ const SizeType sqrt_size_max = sqrt_size_type_max<SizeType>::value;
+ return //Fast runtime check
+ ( (a | b) > sqrt_size_max &&
+ //Slow division check
+ b && a > SizeType(-1)/b
+ );
+}
+
+template<std::size_t SztSizeOfType, class SizeType>
+inline bool size_overflows(SizeType count)
+{
+ //Compile time-check
+ BOOST_STATIC_ASSERT(SztSizeOfType <= SizeType(-1));
+ //Runtime check
+ return multiplication_overflows(SizeType(SztSizeOfType), count);
+}
+
+template<class RawPointer>
+class pointer_size_t_caster
+{
+ public:
+ BOOST_STATIC_ASSERT(sizeof(std::size_t) == sizeof(void*));
+
+ explicit pointer_size_t_caster(std::size_t sz)
+ : m_ptr(reinterpret_cast<RawPointer>(sz))
+ {}
+
+ explicit pointer_size_t_caster(RawPointer p)
+ : m_ptr(p)
+ {}
+
+ std::size_t size() const
+ { return reinterpret_cast<std::size_t>(m_ptr); }
+
+ RawPointer pointer() const
+ { return m_ptr; }
+
+ private:
+ RawPointer m_ptr;
+};
+
+
+template<class SizeType>
+inline bool sum_overflows(SizeType a, SizeType b)
+{ return SizeType(-1) - a < b; }
+
//Anti-exception node eraser
template<class Cont>
class value_eraser
@@ -140,7 +200,7 @@ class value_eraser
public:
value_eraser(Cont & cont, typename Cont::iterator it)
: m_cont(cont), m_index_it(it), m_erase(true){}
- ~value_eraser()
+ ~value_eraser()
{ if(m_erase) m_cont.erase(m_index_it); }
void release() { m_erase = false; }
diff --git a/boost/interprocess/detail/variadic_templates_tools.hpp b/boost/interprocess/detail/variadic_templates_tools.hpp
index 482a0056a7..80154e05d2 100644
--- a/boost/interprocess/detail/variadic_templates_tools.hpp
+++ b/boost/interprocess/detail/variadic_templates_tools.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
#define BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/detail/win32_api.hpp b/boost/interprocess/detail/win32_api.hpp
index c53725ca3b..d9d3e70330 100644
--- a/boost/interprocess/detail/win32_api.hpp
+++ b/boost/interprocess/detail/win32_api.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -8,248 +8,154 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_INTERPROCESS_WIN32_PRIMITIVES_HPP
-#define BOOST_INTERPROCESS_WIN32_PRIMITIVES_HPP
+#ifndef BOOST_INTERPROCESS_WIN32_API_HPP
+#define BOOST_INTERPROCESS_WIN32_API_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
#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 <cstdlib>
+#include <cstdio>
+
+#include <boost/assert.hpp>
#include <string>
#include <vector>
#include <memory>
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#ifdef BOOST_USE_WINDOWS_H
+#include <windows.h>
+#include <Wbemidl.h>
+#include <Objbase.h>
+#include <Shlobj.h>
+#endif
+
+#if defined(_MSC_VER)
# pragma once
-# pragma comment( lib, "advapi32.lib" )
+# pragma comment( lib, "Advapi32.lib" )
# pragma comment( lib, "oleaut32.lib" )
# pragma comment( lib, "Ole32.lib" )
# pragma comment( lib, "Psapi.lib" )
+# pragma comment( lib, "Shell32.lib" ) //SHGetSpecialFolderPathA
#endif
-#if (defined BOOST_INTERPROCESS_WINDOWS)
+#if defined (BOOST_INTERPROCESS_WINDOWS)
# include <cstdarg>
# include <boost/detail/interlocked.hpp>
#else
# error "This file can only be included in Windows OS"
#endif
+//////////////////////////////////////////////////////////////////////////////
+//
+// Declaration of Windows structures or typedefs if BOOST_USE_WINDOWS_H is used
+//
+//////////////////////////////////////////////////////////////////////////////
-//The structures used in Interprocess with the
-//same binary interface as windows ones
-namespace boost {
-namespace interprocess {
+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_invalid_handle = 6L;
-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;
+//Own defines
+static const unsigned long MaxPath = 260;
-static const unsigned long semaphore_all_access = (0x000F0000L)|(0x00100000L)|0x3;
-static const unsigned long mutex_all_access = (0x000F0000L)|(0x00100000L)|0x0001;
+#ifndef BOOST_USE_WINDOWS_H
-static const unsigned long page_readonly = 0x02;
-static const unsigned long page_readwrite = 0x04;
-static const unsigned long page_writecopy = 0x08;
+struct GUID_BIPC
+{
+ unsigned long Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[8];
+};
-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;
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning (disable : 4201) // nonstandard extension used
+#endif
-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;
+struct decimal
+{
+ unsigned short wReserved;
+ union {
+ struct {
+ unsigned char scale;
+ unsigned char sign;
+ };
+ unsigned short signscale;
+ };
+ unsigned long Hi32;
+ union {
+ struct {
+ unsigned long Lo32;
+ unsigned long Mid32;
+ };
+ unsigned __int64 Lo64;
+ };
+};
-//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;
+typedef unsigned short *bstr;
-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;
+struct wchar_variant
+{
+ union
+ {
+ struct
+ {
+ unsigned short vt;
+ unsigned short wReserved1;
+ unsigned short wReserved2;
+ unsigned short wReserved3;
+ union
+ {
+ bstr bstrVal;
+ struct
+ {
+ void* pvRecord;
+ void* pRecInfo;
+ };
+ };
+ };
+ decimal decVal;
+ };
+};
-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;
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
-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 file_type_char = 0x0002L;
-static const unsigned long file_type_disk = 0x0001L;
-static const unsigned long file_type_pipe = 0x0003L;
-static const unsigned long file_type_remote = 0x8000L;
-static const unsigned long file_type_unknown = 0x0000L;
-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;
-const signed long RPC_E_CHANGED_MODE_BIPC = 0x80010106L;
-const unsigned long COINIT_APARTMENTTHREADED_BIPC = 0x2;
-const unsigned long COINIT_MULTITHREADED_BIPC = 0x0;
-const unsigned long COINIT_DISABLE_OLE1DDE_BIPC = 0x4;
-const unsigned long COINIT_SPEED_OVER_MEMORY_BIPC = 0x4;
-//If the user needs to change default COM initialization model,
-//it can define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL to one of these:
-//
-// COINIT_APARTMENTTHREADED_BIPC
-// COINIT_MULTITHREADED_BIPC
-// COINIT_DISABLE_OLE1DDE_BIPC
-// COINIT_SPEED_OVER_MEMORY_BIPC
-#if !defined(BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL)
- #define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL COINIT_APARTMENTTHREADED_BIPC
-#elif (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_APARTMENTTHREADED_BIPC) &&\
- (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_MULTITHREADED_BIPC) &&\
- (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_DISABLE_OLE1DDE_BIPC) &&\
- (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_SPEED_OVER_MEMORY_BIPC)
- #error "Wrong value for BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL macro"
-#endif
-} //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
+struct IUnknown_BIPC
{
- 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;
+ public:
+ virtual long __stdcall QueryInterface(
+ const GUID_BIPC &riid, // [in]
+ void **ppvObject) = 0; // [iid_is][out]
- virtual unsigned long __stdcall Release( void) = 0;
- };
+ virtual unsigned long __stdcall AddRef (void) = 0;
+ virtual unsigned long __stdcall Release(void) = 0;
+};
struct IWbemClassObject_BIPC : public IUnknown_BIPC
{
@@ -258,23 +164,23 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC
/* [out] */ void **ppQualSet) = 0;
virtual long __stdcall Get(
- /* [string][in] */ const wchar_t * wszName,
+ /* [string][in] */ const bstr wszName,
/* [in] */ long lFlags,
/* [unique][in][out] */ wchar_variant *pVal,
/* [unique][in][out] */ long *pType,
/* [unique][in][out] */ long *plFlavor) = 0;
virtual long __stdcall Put(
- /* [string][in] */ const wchar_t * wszName,
+ /* [string][in] */ const bstr wszName,
/* [in] */ long lFlags,
/* [in] */ wchar_variant *pVal,
/* [in] */ long Type) = 0;
virtual long __stdcall Delete(
- /* [string][in] */ const wchar_t * wszName) = 0;
+ /* [string][in] */ const bstr wszName) = 0;
virtual long __stdcall GetNames(
- /* [string][in] */ const wchar_t * wszQualifierName,
+ /* [string][in] */ const bstr wszQualifierName,
/* [in] */ long lFlags,
/* [in] */ wchar_variant *pQualifierVal,
/* [out] */ void * *pNames) = 0;
@@ -284,7 +190,7 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC
virtual long __stdcall Next(
/* [in] */ long lFlags,
- /* [unique][in][out] */ wchar_t * *strName,
+ /* [unique][in][out] */ bstr *strName,
/* [unique][in][out] */ wchar_variant *pVal,
/* [unique][in][out] */ long *pType,
/* [unique][in][out] */ long *plFlavor) = 0;
@@ -292,7 +198,7 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC
virtual long __stdcall EndEnumeration( void) = 0;
virtual long __stdcall GetPropertyQualifierSet(
- /* [string][in] */ const wchar_t * wszProperty,
+ /* [string][in] */ const bstr wszProperty,
/* [out] */ void **ppQualSet) = 0;
virtual long __stdcall Clone(
@@ -300,7 +206,7 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC
virtual long __stdcall GetObjectText(
/* [in] */ long lFlags,
- /* [out] */ wchar_t * *pstrObjectText) = 0;
+ /* [out] */ bstr *pstrObjectText) = 0;
virtual long __stdcall SpawnDerivedClass(
/* [in] */ long lFlags,
@@ -315,49 +221,48 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC
/* [in] */ IWbemClassObject_BIPC *pCompareTo) = 0;
virtual long __stdcall GetPropertyOrigin(
- /* [string][in] */ const wchar_t * wszName,
- /* [out] */ wchar_t * *pstrClassName) = 0;
+ /* [string][in] */ const bstr wszName,
+ /* [out] */ bstr *pstrClassName) = 0;
virtual long __stdcall InheritsFrom(
- /* [in] */ const wchar_t * strAncestor) = 0;
+ /* [in] */ const bstr strAncestor) = 0;
virtual long __stdcall GetMethod(
- /* [string][in] */ const wchar_t * wszName,
+ /* [string][in] */ const bstr wszName,
/* [in] */ long lFlags,
/* [out] */ IWbemClassObject_BIPC **ppInSignature,
/* [out] */ IWbemClassObject_BIPC **ppOutSignature) = 0;
virtual long __stdcall PutMethod(
- /* [string][in] */ const wchar_t * wszName,
+ /* [string][in] */ const bstr wszName,
/* [in] */ long lFlags,
/* [in] */ IWbemClassObject_BIPC *pInSignature,
/* [in] */ IWbemClassObject_BIPC *pOutSignature) = 0;
virtual long __stdcall DeleteMethod(
- /* [string][in] */ const wchar_t * wszName) = 0;
+ /* [string][in] */ const bstr 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] */ bstr *pstrName,
/* [unique][in][out] */ IWbemClassObject_BIPC **ppInSignature,
/* [unique][in][out] */ IWbemClassObject_BIPC **ppOutSignature) = 0;
virtual long __stdcall EndMethodEnumeration( void) = 0;
virtual long __stdcall GetMethodQualifierSet(
- /* [string][in] */ const wchar_t * wszMethod,
+ /* [string][in] */ const bstr wszMethod,
/* [out] */ void **ppQualSet) = 0;
virtual long __stdcall GetMethodOrigin(
- /* [string][in] */ const wchar_t * wszMethodName,
- /* [out] */ wchar_t * *pstrClassName) = 0;
+ /* [string][in] */ const bstr wszMethodName,
+ /* [out] */ bstr *pstrClassName) = 0;
};
-
struct IWbemContext_BIPC : public IUnknown_BIPC
{
public:
@@ -373,23 +278,23 @@ public:
virtual long __stdcall Next(
/* [in] */ long lFlags,
- /* [out] */ wchar_t * *pstrName,
+ /* [out] */ bstr *pstrName,
/* [out] */ wchar_variant *pValue) = 0;
virtual long __stdcall EndEnumeration( void) = 0;
virtual long __stdcall SetValue(
- /* [string][in] */ const wchar_t * wszName,
+ /* [string][in] */ const bstr wszName,
/* [in] */ long lFlags,
/* [in] */ wchar_variant *pValue) = 0;
virtual long __stdcall GetValue(
- /* [string][in] */ const wchar_t * wszName,
+ /* [string][in] */ const bstr wszName,
/* [in] */ long lFlags,
/* [out] */ wchar_variant *pValue) = 0;
virtual long __stdcall DeleteValue(
- /* [string][in] */ const wchar_t * wszName,
+ /* [string][in] */ const bstr wszName,
/* [in] */ long lFlags) = 0;
virtual long __stdcall DeleteAll( void) = 0;
@@ -425,7 +330,7 @@ struct IWbemServices_BIPC : public IUnknown_BIPC
{
public:
virtual long __stdcall OpenNamespace(
- /* [in] */ const wchar_t * strNamespace,
+ /* [in] */ const bstr strNamespace,
/* [in] */ long lFlags,
/* [in] */ void *pCtx,
/* [unique][in][out] */ void **ppWorkingNamespace,
@@ -439,14 +344,14 @@ public:
/* [out] */ void **ppResponseHandler) = 0;
virtual long __stdcall GetObject(
- /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ const bstr strObjectPath,
/* [in] */ long lFlags,
/* [in] */ void *pCtx,
/* [unique][in][out] */ void **ppObject,
/* [unique][in][out] */ void **ppCallResult) = 0;
virtual long __stdcall GetObjectAsync(
- /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ const bstr strObjectPath,
/* [in] */ long lFlags,
/* [in] */ void *pCtx,
/* [in] */ void *pResponseHandler) = 0;
@@ -464,25 +369,25 @@ public:
/* [in] */ void *pResponseHandler) = 0;
virtual long __stdcall DeleteClass(
- /* [in] */ const wchar_t * strClass,
+ /* [in] */ const bstr strClass,
/* [in] */ long lFlags,
/* [in] */ void *pCtx,
/* [unique][in][out] */ void **ppCallResult) = 0;
virtual long __stdcall DeleteClassAsync(
- /* [in] */ const wchar_t * strClass,
+ /* [in] */ const bstr strClass,
/* [in] */ long lFlags,
/* [in] */ void *pCtx,
/* [in] */ void *pResponseHandler) = 0;
virtual long __stdcall CreateClassEnum(
- /* [in] */ const wchar_t * strSuperclass,
+ /* [in] */ const bstr strSuperclass,
/* [in] */ long lFlags,
/* [in] */ void *pCtx,
/* [out] */ void **ppEnum) = 0;
virtual long __stdcall CreateClassEnumAsync(
- /* [in] */ const wchar_t * strSuperclass,
+ /* [in] */ const bstr strSuperclass,
/* [in] */ long lFlags,
/* [in] */ void *pCtx,
/* [in] */ void *pResponseHandler) = 0;
@@ -500,60 +405,60 @@ public:
/* [in] */ void *pResponseHandler) = 0;
virtual long __stdcall DeleteInstance(
- /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ const bstr strObjectPath,
/* [in] */ long lFlags,
/* [in] */ void *pCtx,
/* [unique][in][out] */ void **ppCallResult) = 0;
virtual long __stdcall DeleteInstanceAsync(
- /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ const bstr strObjectPath,
/* [in] */ long lFlags,
/* [in] */ void *pCtx,
/* [in] */ void *pResponseHandler) = 0;
virtual long __stdcall CreateInstanceEnum(
- /* [in] */ const wchar_t * strFilter,
+ /* [in] */ const bstr strFilter,
/* [in] */ long lFlags,
/* [in] */ void *pCtx,
/* [out] */ void **ppEnum) = 0;
virtual long __stdcall CreateInstanceEnumAsync(
- /* [in] */ const wchar_t * strFilter,
+ /* [in] */ const bstr 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] */ const bstr strQueryLanguage,
+ /* [in] */ const bstr strQuery,
/* [in] */ long lFlags,
/* [in] */ IWbemContext_BIPC *pCtx,
/* [out] */ IEnumWbemClassObject_BIPC **ppEnum) = 0;
virtual long __stdcall ExecQueryAsync(
- /* [in] */ const wchar_t * strQueryLanguage,
- /* [in] */ const wchar_t * strQuery,
+ /* [in] */ const bstr strQueryLanguage,
+ /* [in] */ const bstr strQuery,
/* [in] */ long lFlags,
/* [in] */ IWbemContext_BIPC *pCtx,
/* [in] */ void *pResponseHandler) = 0;
virtual long __stdcall ExecNotificationQuery(
- /* [in] */ const wchar_t * strQueryLanguage,
- /* [in] */ const wchar_t * strQuery,
+ /* [in] */ const bstr strQueryLanguage,
+ /* [in] */ const bstr strQuery,
/* [in] */ long lFlags,
/* [in] */ IWbemContext_BIPC *pCtx,
/* [out] */ void **ppEnum) = 0;
virtual long __stdcall ExecNotificationQueryAsync(
- /* [in] */ const wchar_t * strQueryLanguage,
- /* [in] */ const wchar_t * strQuery,
+ /* [in] */ const bstr strQueryLanguage,
+ /* [in] */ const bstr strQuery,
/* [in] */ long lFlags,
/* [in] */ IWbemContext_BIPC *pCtx,
/* [in] */ void *pResponseHandler) = 0;
virtual long __stdcall ExecMethod(
- /* [in] */ const wchar_t * strObjectPath,
- /* [in] */ const wchar_t * strMethodName,
+ /* [in] */ const bstr strObjectPath,
+ /* [in] */ const bstr strMethodName,
/* [in] */ long lFlags,
/* [in] */ IWbemContext_BIPC *pCtx,
/* [in] */ IWbemClassObject_BIPC *pInParams,
@@ -561,8 +466,8 @@ public:
/* [unique][in][out] */ void **ppCallResult) = 0;
virtual long __stdcall ExecMethodAsync(
- /* [in] */ const wchar_t * strObjectPath,
- /* [in] */ const wchar_t * strMethodName,
+ /* [in] */ const bstr strObjectPath,
+ /* [in] */ const bstr strMethodName,
/* [in] */ long lFlags,
/* [in] */ IWbemContext_BIPC *pCtx,
/* [in] */ IWbemClassObject_BIPC *pInParams,
@@ -574,19 +479,17 @@ 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] */ const bstr strNetworkResource,
+ /* [in] */ const bstr strUser,
+ /* [in] */ const bstr strPassword,
+ /* [in] */ const bstr strLocale,
/* [in] */ long lSecurityFlags,
- /* [in] */ const wchar_t * strAuthority,
+ /* [in] */ const bstr strAuthority,
/* [in] */ void *pCtx,
/* [out] */ IWbemServices_BIPC **ppNamespace) = 0;
};
-
-
struct interprocess_overlapped
{
unsigned long *internal;
@@ -602,18 +505,6 @@ struct interprocess_overlapped
void *h_event;
};
-struct interprocess_semaphore_basic_information
-{
- unsigned int count; // current semaphore count
- unsigned int limit; // max semaphore count
-};
-
-struct interprocess_section_basic_information
-{
- void * base_address;
- unsigned long section_attributes;
- __int64 section_size;
-};
struct interprocess_filetime
{
@@ -621,7 +512,7 @@ struct interprocess_filetime
unsigned long dwHighDateTime;
};
-struct win32_find_data_t
+struct win32_find_data
{
unsigned long dwFileAttributes;
interprocess_filetime ftCreationTime;
@@ -661,27 +552,16 @@ struct system_info {
unsigned short wProcessorRevision;
};
-typedef struct _interprocess_memory_basic_information
-{
- void * BaseAddress;
- void * AllocationBase;
- unsigned long AllocationProtect;
- unsigned long RegionSize;
- unsigned long State;
- unsigned long Protect;
- unsigned long Type;
-} interprocess_memory_basic_information;
-
-typedef struct _interprocess_acl
+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
+struct interprocess_security_descriptor
{
unsigned char Revision;
unsigned char Sbz1;
@@ -690,59 +570,134 @@ typedef struct _interprocess_security_descriptor
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 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 semaphore_information_class {
- semaphore_basic_information = 0
+struct interprocess_eventlogrecord
+{
+ unsigned long Length; // Length of full record
+ unsigned long Reserved; // Used by the service
+ unsigned long RecordNumber; // Absolute record number
+ unsigned long TimeGenerated; // Seconds since 1-1-1970
+ unsigned long TimeWritten; // Seconds since 1-1-1970
+ unsigned long EventID;
+ unsigned short EventType;
+ unsigned short NumStrings;
+ unsigned short EventCategory;
+ unsigned short ReservedFlags; // For use with paired events (auditing)
+ unsigned long ClosingRecordNumber; // For use with paired events (auditing)
+ unsigned long StringOffset; // Offset from beginning of record
+ unsigned long UserSidLength;
+ unsigned long UserSidOffset;
+ unsigned long DataLength;
+ unsigned long DataOffset; // Offset from beginning of record
+ //
+ // Then follow:
+ //
+ // wchar_t SourceName[]
+ // wchar_t Computername[]
+ // SID UserSid
+ // wchar_t Strings[]
+ // BYTE Data[]
+ // CHAR Pad[]
+ // unsigned long Length;
+ //
};
-struct file_name_information_t {
- unsigned long FileNameLength;
- wchar_t FileName[1];
+union large_integer
+{
+ __int64 QuadPart;
+};
+
+struct hinstance_struct { int unused; };
+typedef hinstance_struct *hmodule;
+
+struct hkey_struct;
+typedef hkey_struct *hkey;
+
+#ifdef _WIN64
+typedef __int64 (__stdcall *farproc_t)();
+#else
+typedef int (__stdcall *farproc_t)();
+#endif // _WIN64
+
+#else //#ifndef BOOST_USE_WINDOWS_H
+
+typedef GUID GUID_BIPC;
+typedef VARIANT wchar_variant;
+
+typedef IUnknown IUnknown_BIPC;
+
+typedef IWbemClassObject IWbemClassObject_BIPC;
+
+typedef IWbemContext IWbemContext_BIPC;
+
+typedef IEnumWbemClassObject IEnumWbemClassObject_BIPC;
+
+typedef IWbemServices IWbemServices_BIPC;
+
+typedef IWbemLocator IWbemLocator_BIPC;
+
+typedef OVERLAPPED interprocess_overlapped;
+
+typedef FILETIME interprocess_filetime;
+
+typedef WIN32_FIND_DATAA win32_find_data;
+
+typedef SECURITY_ATTRIBUTES interprocess_security_attributes;
+
+typedef SYSTEM_INFO system_info;
+
+typedef ACL interprocess_acl;
+
+typedef SECURITY_DESCRIPTOR interprocess_security_descriptor;
+
+typedef BY_HANDLE_FILE_INFORMATION interprocess_by_handle_file_information;
+
+typedef EVENTLOGRECORD interprocess_eventlogrecord;
+
+typedef LARGE_INTEGER large_integer;
+
+typedef HMODULE hmodule;
+
+typedef HKEY hkey;
+
+typedef BSTR bstr;
+
+typedef FARPROC farproc_t;
+
+#endif //#ifndef BOOST_USE_WINDOWS_H
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Nt native structures
+//
+//////////////////////////////////////////////////////////////////////////////
+
+struct interprocess_semaphore_basic_information
+{
+ unsigned int count; // current semaphore count
+ unsigned int limit; // max semaphore count
+};
+
+struct interprocess_section_basic_information
+{
+ void * base_address;
+ unsigned long section_attributes;
+ __int64 section_size;
};
struct file_rename_information_t {
@@ -785,24 +740,71 @@ union system_timeofday_information
__int64 liExpTimeZoneBias;
unsigned long uCurrentTimeZoneId;
unsigned long dwReserved;
+ unsigned __int64 ullBootTimeBias;
+ unsigned __int64 ullSleepTimeBias;
} data;
- unsigned char Reserved1[SystemTimeOfDayInfoLength];
+ unsigned char Reserved1[sizeof(data_t)];
};
-struct interprocess_by_handle_file_information
+static const long BootstampLength = sizeof(__int64);
+static const long BootAndSystemstampLength = sizeof(__int64)*2;
+static const long SystemTimeOfDayInfoLength = sizeof(system_timeofday_information::data_t);
+
+struct object_name_information_t
{
- 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;
+ unicode_string_t Name;
+ wchar_t NameBuffer[1];
};
+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
+};
+
+enum semaphore_information_class {
+ semaphore_basic_information = 0
+};
+
+
enum system_information_class {
system_basic_information = 0,
system_performance_information = 2,
@@ -830,11 +832,15 @@ enum section_information_class
section_image_information
};
-struct object_name_information_t
-{
- unicode_string_t Name;
- wchar_t NameBuffer[1];
-};
+//////////////////////////////////////////////////////////////////////////////
+//
+// Forward declaration of winapi
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_USE_WINDOWS_H
+
+//Kernel32.dll
//Some windows API declarations
extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
@@ -844,6 +850,7 @@ extern "C" __declspec(dllimport) int __stdcall GetProcessTimes
, interprocess_filetime *lpExitTime,interprocess_filetime *lpKernelTime
, interprocess_filetime *lpUserTime );
extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long);
+extern "C" __declspec(dllimport) unsigned long __stdcall GetTickCount(void);
extern "C" __declspec(dllimport) int __stdcall SwitchToThread();
extern "C" __declspec(dllimport) unsigned long __stdcall GetLastError();
extern "C" __declspec(dllimport) void __stdcall SetLastError(unsigned long);
@@ -855,8 +862,8 @@ extern "C" __declspec(dllimport) int __stdcall DuplicateHandle
, unsigned long dwDesiredAccess, int bInheritHandle
, unsigned long dwOptions);
extern "C" __declspec(dllimport) long __stdcall GetFileType(void *hFile);
-extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data_t *lpFindFileData);
-extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data_t *lpFindFileData);
+extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data *lpFindFileData);
+extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data *lpFindFileData);
extern "C" __declspec(dllimport) int __stdcall FindClose(void *hFindFile);
//extern "C" __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(interprocess_filetime*);
//extern "C" __declspec(dllimport) int __stdcall FileTimeToLocalFileTime(const interprocess_filetime *in, const interprocess_filetime *out);
@@ -872,12 +879,12 @@ extern "C" __declspec(dllimport) void * __stdcall CreateFileMappingA (void *, in
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 VirtualUnlock (void *, std::size_t);
+extern "C" __declspec(dllimport) int __stdcall VirtualProtect (void *, std::size_t, unsigned long, unsigned long *);
extern "C" __declspec(dllimport) int __stdcall FlushFileBuffers (void *);
-extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, __int64 *size);
+extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, large_integer *size);
extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA
(unsigned long dwFlags, const void *lpSource, unsigned long dwMessageId,
unsigned long dwLanguageId, char *lpBuffer, unsigned long nSize,
@@ -890,7 +897,7 @@ extern "C" __declspec(dllimport) int __stdcall GetTempPathA(unsigned long length
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 SetFilePointerEx(void *, large_integer distance, large_integer *new_file_pointer, unsigned long move_method);
extern "C" __declspec(dllimport) int __stdcall LockFile (void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high);
extern "C" __declspec(dllimport) int __stdcall UnlockFile(void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high);
extern "C" __declspec(dllimport) int __stdcall LockFileEx(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped);
@@ -899,18 +906,18 @@ extern "C" __declspec(dllimport) int __stdcall WriteFile(void *hnd, const void *
extern "C" __declspec(dllimport) int __stdcall ReadFile(void *hnd, void *buffer, unsigned long bytes_to_read, unsigned long *bytes_read, interprocess_overlapped* overlapped);
extern "C" __declspec(dllimport) int __stdcall InitializeSecurityDescriptor(interprocess_security_descriptor *pSecurityDescriptor, unsigned long dwRevision);
extern "C" __declspec(dllimport) int __stdcall SetSecurityDescriptorDacl(interprocess_security_descriptor *pSecurityDescriptor, int bDaclPresent, interprocess_acl *pDacl, int bDaclDefaulted);
-extern "C" __declspec(dllimport) 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) hmodule __stdcall LoadLibraryA(const char *);
+extern "C" __declspec(dllimport) int __stdcall FreeLibrary(hmodule);
+extern "C" __declspec(dllimport) farproc_t __stdcall GetProcAddress(void *, const char*);
+extern "C" __declspec(dllimport) hmodule __stdcall GetModuleHandleA(const char*);
extern "C" __declspec(dllimport) void *__stdcall GetFileInformationByHandle(void *, interprocess_by_handle_file_information*);
-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
+//Advapi32.dll
+extern "C" __declspec(dllimport) long __stdcall RegOpenKeyExA(hkey, const char *, unsigned long, unsigned long, hkey*);
+extern "C" __declspec(dllimport) long __stdcall RegQueryValueExA(hkey, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*);
+extern "C" __declspec(dllimport) long __stdcall RegCloseKey(hkey);
+
+//Ole32.dll
extern "C" __declspec(dllimport) long __stdcall CoInitializeEx(void *pvReserved, unsigned long dwCoInit);
extern "C" __declspec(dllimport) long __stdcall CoInitializeSecurity(
void* pSecDesc,
@@ -932,18 +939,47 @@ extern "C" __declspec(dllimport) long __stdcall CoInitializeSecurity(
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);
+//OleAut32.dll
+extern "C" __declspec(dllimport) long __stdcall VariantClear(wchar_variant * pvarg);
+
+//Shell32.dll
+extern "C" __declspec(dllimport) int __stdcall SHGetSpecialFolderPathA
+ (void* hwnd, const char *pszPath, int csidl, int fCreate);
+
+extern "C" __declspec(dllimport) int __stdcall SHGetFolderPathA(void *hwnd, int csidl, void *hToken, unsigned long dwFlags, const char *pszPath);
+
+//EventLog access functions
+extern "C" __declspec(dllimport) void* __stdcall OpenEventLogA
+ (const char* lpUNCServerName, const char* lpSourceName);
-//API function typedefs
-//Pointer to functions
+extern "C" __declspec(dllimport) int __stdcall CloseEventLog(void *hEventLog);
+
+extern "C" __declspec(dllimport) int __stdcall ReadEventLogA
+ (void *hEventLog,
+ unsigned long dwReadFlags,
+ unsigned long dwRecordOffset,
+ void *lpBuffer,
+ unsigned long nNumberOfBytesToRead,
+ unsigned long *pnBytesRead,
+ unsigned long *pnMinNumberOfBytesNeeded
+ );
+
+#endif //#ifndef BOOST_USE_WINDOWS_H
+
+//kernel32.dll
+typedef int (__stdcall *QueryPerformanceCounter_t) (__int64 *lpPerformanceCount);
+typedef int (__stdcall *QueryPerformanceFrequency_t)(__int64 *lpFrequency);
+
+//ntdll.dll
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 *NtOpenFile)(void **FileHandle, unsigned long DesiredAccess, object_attributes_t *ObjectAttributes
+ , io_status_block_t *IoStatusBlock, unsigned long ShareAccess, unsigned long Length, unsigned long OpenOptions);
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 *NtQuerySemaphore_t)(void*, unsigned int info_class, interprocess_semaphore_basic_information *pinfo, unsigned int info_size, unsigned int *ret_len);
@@ -951,19 +987,203 @@ typedef long (__stdcall *NtQuerySection_t)(void*, section_information_class, int
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 *);
+typedef long (__stdcall *NtQueryTimerResolution_t) (unsigned long* LowestResolution, unsigned long* HighestResolution, unsigned long* CurrentResolution);
+typedef long (__stdcall *NtSetTimerResolution_t) (unsigned long RequestedResolution, int Set, unsigned long* ActualResolution);
+
+} //namespace winapi {
+} //namespace interprocess {
+} //namespace boost {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Forward declaration of constants
+//
+//////////////////////////////////////////////////////////////////////////////
+
+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_invalid_handle = 6L;
+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;
+static const unsigned long error_not_locked = 158L;
+//Retries in CreateFile, see http://support.microsoft.com/kb/316609
+static const unsigned long error_sharing_violation_tries = 3L;
+static const unsigned long error_sharing_violation_sleep_ms = 250L;
+static const unsigned long error_file_too_large = 223L;
+static const unsigned long error_insufficient_buffer = 122L;
+static const unsigned long error_handle_eof = 38L;
+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 page_noaccess = 0x01;
+
+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 long delete_flag = 0x00010000L;
+
+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 file_type_char = 0x0002L;
+static const unsigned long file_type_disk = 0x0001L;
+static const unsigned long file_type_pipe = 0x0003L;
+static const unsigned long file_type_remote = 0x8000L;
+static const unsigned long file_type_unknown = 0x0000L;
+
+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;
+
+const unsigned long max_record_buffer_size = 0x10000L; // 64K
+const unsigned long max_path = 260;
+
+//Keys
+static const hkey hkey_local_machine = (hkey)(unsigned long*)(long)(0x80000002);
+static unsigned long key_query_value = 0x0001;
+
+//COM API
+const unsigned long RPC_C_AUTHN_LEVEL_PKT_BIPC = 4;
+const unsigned long RPC_C_AUTHN_DEFAULT_BIPC = 0xffffffffL;
+const unsigned long RPC_C_AUTHZ_DEFAULT_BIPC = 0xffffffffL;
+const unsigned long RPC_C_IMP_LEVEL_IMPERSONATE_BIPC = 3;
+const signed long EOAC_NONE_BIPC = 0;
+const signed long CLSCTX_INPROC_SERVER_BIPC = 0x1;
+const signed long CLSCTX_LOCAL_SERVER_BIPC = 0x4;
+const signed long WBEM_FLAG_RETURN_IMMEDIATELY_BIPC = 0x10;
+const signed long WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC = 0x0;
+const signed long WBEM_FLAG_FORWARD_ONLY_BIPC = 0x20;
+const signed long WBEM_INFINITE_BIPC = 0xffffffffL;
+const signed long RPC_E_TOO_LATE_BIPC = 0x80010119L;
+const signed long S_OK_BIPC = 0L;
+const signed long S_FALSE_BIPC = 1;
+const signed long RPC_E_CHANGED_MODE_BIPC = 0x80010106L;
+const unsigned long COINIT_APARTMENTTHREADED_BIPC = 0x2;
+const unsigned long COINIT_MULTITHREADED_BIPC = 0x0;
+const unsigned long COINIT_DISABLE_OLE1DDE_BIPC = 0x4;
+const unsigned long COINIT_SPEED_OVER_MEMORY_BIPC = 0x4;
+
+
+//If the user needs to change default COM initialization model,
+//it can define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL to one of these:
+//
+// COINIT_APARTMENTTHREADED_BIPC
+// COINIT_MULTITHREADED_BIPC
+// COINIT_DISABLE_OLE1DDE_BIPC
+// COINIT_SPEED_OVER_MEMORY_BIPC
+#if !defined(BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL)
+ #define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL COINIT_APARTMENTTHREADED_BIPC
+#elif (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_APARTMENTTHREADED_BIPC) &&\
+ (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_MULTITHREADED_BIPC) &&\
+ (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_DISABLE_OLE1DDE_BIPC) &&\
+ (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_SPEED_OVER_MEMORY_BIPC)
+ #error "Wrong value for BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL macro"
+#endif
+
+const GUID_BIPC CLSID_WbemAdministrativeLocator =
+ { 0xcb8555cc, 0x9128, 0x11d1, {0xad, 0x9b, 0x00, 0xc0, 0x4f, 0xd8, 0xfd, 0xff}};
+
+const GUID_BIPC IID_IUnknown = { 0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
+
+static const unsigned long eventlog_sequential_read = 0x0001;
+static const unsigned long eventlog_backwards_read = 0x0008;
} //namespace winapi {
} //namespace interprocess {
} //namespace boost {
+
namespace boost {
namespace interprocess {
namespace winapi {
@@ -993,10 +1213,13 @@ inline unsigned long make_lang_id(unsigned long p, unsigned long s)
inline void sched_yield()
{
if(!SwitchToThread()){
- Sleep(1);
+ Sleep(0);
}
}
+inline void sleep_tick()
+{ Sleep(1); }
+
inline void sleep(unsigned long ms)
{ Sleep(ms); }
@@ -1015,10 +1238,10 @@ inline unsigned long get_current_process_id()
inline unsigned int close_handle(void* handle)
{ return CloseHandle(handle); }
-inline void * find_first_file(const char *lpFileName, win32_find_data_t *lpFindFileData)
+inline void * find_first_file(const char *lpFileName, win32_find_data *lpFindFileData)
{ return FindFirstFileA(lpFileName, lpFindFileData); }
-inline bool find_next_file(void *hFindFile, win32_find_data_t *lpFindFileData)
+inline bool find_next_file(void *hFindFile, win32_find_data *lpFindFileData)
{ return FindNextFileA(hFindFile, lpFindFileData) != 0; }
inline bool find_close(void *handle)
@@ -1033,7 +1256,7 @@ inline bool duplicate_current_process_handle
, duplicate_same_access);
}
-inline long get_file_type(void *hFile)
+inline unsigned long get_file_type(void *hFile)
{
return GetFileType(hFile);
}
@@ -1125,23 +1348,23 @@ inline void *create_file(const char *name, unsigned long access, unsigned long c
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 virtual_unlock(void *base_addr, std::size_t numbytes)
+{ return 0 != VirtualUnlock(base_addr, numbytes); }
+
+inline bool virtual_protect(void *base_addr, std::size_t numbytes, unsigned long flNewProtect, unsigned long &lpflOldProtect)
+{ return 0 != VirtualProtect(base_addr, numbytes, flNewProtect, &lpflOldProtect); }
+
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); }
+{ return 0 != GetFileSizeEx(handle, (large_integer*)&size); }
inline bool create_directory(const char *name)
{
@@ -1159,7 +1382,10 @@ 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); }
+{
+ large_integer d; d.QuadPart = distance;
+ return 0 != SetFilePointerEx(handle, d, (large_integer*)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); }
@@ -1192,38 +1418,30 @@ 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)
+inline hmodule load_library(const char *name)
{ return LoadLibraryA(name); }
-inline bool free_library(void *module)
+inline bool free_library(hmodule module)
{ return 0 != FreeLibrary(module); }
-inline void *get_proc_address(void *module, const char *name)
+inline farproc_t get_proc_address(hmodule module, const char *name)
{ return GetProcAddress(module, name); }
inline void *get_current_process()
{ return GetCurrentProcess(); }
-inline void *get_module_handle(const char *name)
+inline hmodule 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)
+inline long reg_open_key_ex(hkey hKey, const char *lpSubKey, unsigned long ulOptions, unsigned long samDesired, hkey *phkResult)
{ return RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult); }
-inline long reg_query_value_ex(void *hKey, const char *lpValueName, unsigned long*lpReserved, unsigned long*lpType, unsigned char *lpData, unsigned long*lpcbData)
+inline long reg_query_value_ex(hkey hKey, const char *lpValueName, unsigned long*lpReserved, unsigned long*lpType, unsigned char *lpData, unsigned long*lpcbData)
{ return RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); }
-inline long reg_close_key(void *hKey)
+inline long reg_close_key(hkey 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)
@@ -1248,75 +1466,134 @@ inline void rtl_init_empty_unicode_string(unicode_string_t *ucStr, wchar_t *buf,
template<int Dummy>
struct function_address_holder
{
- enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NtQuerySemaphore, NtQuerySection, NumFunction };
- enum { NtDll_dll, NumModule };
+ enum { NtSetInformationFile
+ , NtQuerySystemInformation
+ , NtQueryObject
+ , NtQuerySemaphore
+ , NtQuerySection
+ , NtOpenFile
+ , NtClose
+ , NtQueryTimerResolution
+ , NtSetTimerResolution
+ , QueryPerformanceCounter
+ , QueryPerformanceFrequency
+ , NumFunction
+ };
+ enum { NtDll_dll, Kernel32_dll, NumModule };
private:
- static void *FunctionAddresses[NumFunction];
+ static const char *FunctionNames[NumFunction];
+ static const char *ModuleNames[NumModule];
+ static farproc_t FunctionAddresses[NumFunction];
+ static unsigned int FunctionModules[NumFunction];
static volatile long FunctionStates[NumFunction];
- static void *ModuleAddresses[NumModule];
+ static hmodule ModuleAddresses[NumModule];
static volatile long ModuleStates[NumModule];
- static void *get_module_from_id(unsigned int id)
+ static hmodule 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]);
+ BOOST_ASSERT(id < (unsigned int)NumModule);
+ hmodule addr = get_module_handle(ModuleNames[id]);
+ BOOST_ASSERT(addr);
+ return addr;
}
- static void *get_module(const unsigned int id)
+ static hmodule get_module(const unsigned int id)
{
- assert(id < (unsigned int)NumModule);
- while(ModuleStates[id] < 2){
+ BOOST_ASSERT(id < (unsigned int)NumModule);
+ for(unsigned i = 0; ModuleStates[id] < 2; ++i){
if(interlocked_compare_exchange(&ModuleStates[id], 1, 0) == 0){
ModuleAddresses[id] = get_module_from_id(id);
interlocked_increment(&ModuleStates[id]);
break;
}
- else{
+ else if(i & 1){
sched_yield();
}
+ else{
+ sleep_tick();
+ }
}
return ModuleAddresses[id];
}
- static void *get_address_from_dll(const unsigned int id)
+ static farproc_t get_address_from_dll(const unsigned int id)
{
- assert(id < (unsigned int)NumFunction);
- const char *function[] = { "NtSetInformationFile", "NtQuerySystemInformation", "NtQueryObject", "NtQuerySemaphore", "NtQuerySection" };
- bool compile_check[sizeof(function)/sizeof(function[0]) == NumFunction];
- (void)compile_check;
- return get_proc_address(get_module(NtDll_dll), function[id]);
+ BOOST_ASSERT(id < (unsigned int)NumFunction);
+ farproc_t addr = get_proc_address(get_module(FunctionModules[id]), FunctionNames[id]);
+ BOOST_ASSERT(addr);
+ return addr;
}
public:
- static void *get(const unsigned int id)
+ static farproc_t get(const unsigned int id)
{
- assert(id < (unsigned int)NumFunction);
- while(FunctionStates[id] < 2){
+ BOOST_ASSERT(id < (unsigned int)NumFunction);
+ for(unsigned i = 0; FunctionStates[id] < 2; ++i){
if(interlocked_compare_exchange(&FunctionStates[id], 1, 0) == 0){
FunctionAddresses[id] = get_address_from_dll(id);
interlocked_increment(&FunctionStates[id]);
break;
}
- else{
+ else if(i & 1){
sched_yield();
}
+ else{
+ sleep_tick();
+ }
}
return FunctionAddresses[id];
}
};
template<int Dummy>
-void *function_address_holder<Dummy>::FunctionAddresses[function_address_holder<Dummy>::NumFunction];
+const char *function_address_holder<Dummy>::FunctionNames[function_address_holder<Dummy>::NumFunction] =
+{
+ "NtSetInformationFile",
+ "NtQuerySystemInformation",
+ "NtQueryObject",
+ "NtQuerySemaphore",
+ "NtQuerySection",
+ "NtOpenFile",
+ "NtClose",
+ "NtQueryTimerResolution",
+ "NtSetTimerResolution",
+ "QueryPerformanceCounter",
+ "QueryPerformanceFrequency"
+};
+
+template<int Dummy>
+unsigned int function_address_holder<Dummy>::FunctionModules[function_address_holder<Dummy>::NumFunction] =
+{
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll,
+ Kernel32_dll,
+ Kernel32_dll
+};
+
+template<int Dummy>
+const char *function_address_holder<Dummy>::ModuleNames[function_address_holder<Dummy>::NumModule] =
+{
+ "ntdll.dll",
+ "kernel32.dll"
+};
+
+
+template<int Dummy>
+farproc_t 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];
+hmodule 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];
@@ -1329,52 +1606,11 @@ struct dll_func
//Complex winapi based functions...
struct library_unloader
{
- void *lib_;
- library_unloader(void *module) : lib_(module){}
+ hmodule lib_;
+ library_unloader(hmodule 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, 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, 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)
{
@@ -1410,7 +1646,8 @@ inline bool get_boot_and_system_time(unsigned char (&bootsystemstamp) [BootAndSy
return true;
}
-inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s) //will write BootstampLength chars
+inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s)
+ //will write BootstampLength chars
{
if(s < (BootstampLength*2))
return false;
@@ -1431,7 +1668,23 @@ inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s) //will write
return true;
}
-inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t &s) //will write BootAndSystemstampLength chars
+//Writes the hexadecimal value of the buffer, in the wide character string.
+//str must be twice length
+inline void buffer_to_wide_str(const void *buf, std::size_t length, wchar_t *str)
+{
+ const wchar_t Characters [] =
+ { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7'
+ , L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' };
+ std::size_t char_counter = 0;
+ const char *chbuf = static_cast<const char *>(buf);
+ for(std::size_t i = 0; i != length; ++i){
+ str[char_counter++] = Characters[(chbuf[i]&0xF0)>>4];
+ str[char_counter++] = Characters[(chbuf[i]&0x0F)];
+ }
+}
+
+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;
@@ -1440,14 +1693,8 @@ inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t
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)];
- }
+
+ buffer_to_wide_str(&info.Reserved1[0], BootAndSystemstampLength, bootsystemstamp);
s = BootAndSystemstampLength*2;
return true;
}
@@ -1463,16 +1710,99 @@ class handle_closer
{ close_handle(handle_); }
};
+class eventlog_handle_closer
+{
+ void *handle_;
+ eventlog_handle_closer(const handle_closer &);
+ eventlog_handle_closer& operator=(const eventlog_handle_closer &);
+ public:
+ explicit eventlog_handle_closer(void *handle) : handle_(handle){}
+ ~eventlog_handle_closer()
+ { CloseEventLog(handle_); }
+};
+
union ntquery_mem_t
{
object_name_information_t name;
struct ren_t
{
file_rename_information_t info;
- wchar_t buf[32767];
+ wchar_t buf[1];
} ren;
};
+class nt_query_mem_deleter
+{
+ static const std::size_t rename_offset = offsetof(ntquery_mem_t, ren.info.FileName) -
+ offsetof(ntquery_mem_t, name.Name.Buffer);
+ // Timestamp process id atomic count
+ static const std::size_t rename_suffix =
+ (SystemTimeOfDayInfoLength + sizeof(unsigned long) + sizeof(boost::uint32_t))*2;
+
+ public:
+ nt_query_mem_deleter(std::size_t object_name_information_size)
+ : m_size(object_name_information_size + rename_offset + rename_suffix)
+ , m_buf(new char [m_size])
+ {}
+
+ ~nt_query_mem_deleter()
+ {
+ delete[]m_buf;
+ }
+
+ void realloc_mem(std::size_t num_bytes)
+ {
+ num_bytes += rename_suffix + rename_offset;
+ char *buf = m_buf;
+ m_buf = new char[num_bytes];
+ delete[]buf;
+ m_size = num_bytes;
+ }
+
+ ntquery_mem_t *query_mem() const
+ { return static_cast<ntquery_mem_t *>(static_cast<void*>(m_buf)); }
+
+ unsigned long object_name_information_size() const
+ {
+ return static_cast<unsigned long>(m_size - rename_offset - SystemTimeOfDayInfoLength*2);
+ }
+
+ std::size_t file_rename_information_size() const
+ { return static_cast<unsigned long>(m_size); }
+
+ private:
+ std::size_t m_size;
+ char *m_buf;
+};
+
+class c_heap_deleter
+{
+ public:
+ c_heap_deleter(std::size_t size)
+ : m_buf(::malloc(size))
+ {}
+
+ ~c_heap_deleter()
+ {
+ if(m_buf) ::free(m_buf);
+ }
+
+ void realloc_mem(std::size_t num_bytes)
+ {
+ void *buf = ::realloc(m_buf, num_bytes);
+ if(!buf){
+ free(m_buf);
+ m_buf = 0;
+ }
+ }
+
+ void *get() const
+ { return m_buf; }
+
+ private:
+ void *m_buf;
+};
+
inline bool unlink_file(const char *filename)
{
//Don't try to optimize doing a DeleteFile first
@@ -1493,71 +1823,96 @@ inline bool unlink_file(const char *filename)
try{
NtSetInformationFile_t pNtSetInformationFile =
(NtSetInformationFile_t)dll_func::get(dll_func::NtSetInformationFile);
- if(!pNtSetInformationFile){
- return false;
- }
- NtQueryObject_t pNtQueryObject =
- (NtQueryObject_t)dll_func::get(dll_func::NtQueryObject);
+ NtQueryObject_t pNtQueryObject = (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);
+ void *fh = create_file(filename, generic_read | delete_access, open_existing, 0, 0);
if(fh == invalid_handle_value){
return false;
}
handle_closer h_closer(fh);
+ {
+ //Obtain name length
+ unsigned long size;
+ const std::size_t initial_string_mem = 512u;
+
+ nt_query_mem_deleter nt_query_mem(sizeof(ntquery_mem_t)+initial_string_mem);
+ //Obtain file name with guessed length
+ if(pNtQueryObject(fh, object_name_information, nt_query_mem.query_mem(), nt_query_mem.object_name_information_size(), &size)){
+ //Obtain file name with exact length buffer
+ nt_query_mem.realloc_mem(size);
+ if(pNtQueryObject(fh, object_name_information, nt_query_mem.query_mem(), nt_query_mem.object_name_information_size(), &size)){
+ return false;
+ }
+ }
+ ntquery_mem_t *pmem = nt_query_mem.query_mem();
+ file_rename_information_t *pfri = &pmem->ren.info;
+ const std::size_t RenMaxNumChars =
+ (((char*)(pmem) + nt_query_mem.file_rename_information_size()) - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t);
+
+ //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);
+
+ //Search '\\' character to replace from it
+ for(std::size_t i = filename_string_length; i != 0; --filename_string_length){
+ if(pmem->ren.info.FileName[--i] == L'\\')
+ break;
+ }
- 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;
+ //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;
+
+ //Sometimes the precission of the timestamp is not enough and we need to add another random number.
+ //The process id (to exclude concurrent processes) and an atomic count (to exclude concurrent threads).
+ //should be enough
+ const unsigned long pid = get_current_process_id();
+ buffer_to_wide_str(&pid, sizeof(pid), &pfri->FileName[filename_string_length]);
+ filename_string_length += sizeof(pid)*2;
+
+ static volatile boost::uint32_t u32_count = 0;
+ interlocked_decrement(reinterpret_cast<volatile long*>(&u32_count));
+ buffer_to_wide_str(const_cast<const boost::uint32_t *>(&u32_count), sizeof(boost::uint32_t), &pfri->FileName[filename_string_length]);
+ filename_string_length += sizeof(boost::uint32_t)*2;
+
+ //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;
+
+ //Cange the name of the in-use file...
+ io_status_block_t io;
+ if(0 != pNtSetInformationFile(fh, &io, pfri, nt_query_mem.file_rename_information_size(), file_rename_information)){
+ 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;
+ //...and mark it as delete-on-close
+ {
+ //Don't use pNtSetInformationFile with file_disposition_information as it can return STATUS_CANNOT_DELETE
+ //if the file is still mapped. Reopen it with NtOpenFile and file_delete_on_close
+ NtOpenFile_t pNtOpenFile = (NtOpenFile_t)dll_func::get(dll_func::NtOpenFile);
+ NtClose_t pNtClose = (NtClose_t)dll_func::get(dll_func::NtClose);
+ const wchar_t empty_str [] = L"";
+ unicode_string_t ustring = { sizeof(empty_str) - sizeof (wchar_t) //length in bytes without null
+ , sizeof(empty_str) //total size in bytes of memory allocated for Buffer.
+ , const_cast<wchar_t*>(empty_str)
+ };
+ object_attributes_t object_attr;
+ initialize_object_attributes(&object_attr, &ustring, 0, fh, 0);
+ void* fh2 = 0;
+ io_status_block_t io;
+ pNtOpenFile( &fh2, delete_flag, &object_attr, &io
+ , file_share_read | file_share_write | file_share_delete, file_delete_on_close);
+ pNtClose(fh2);
+ //Even if NtOpenFile fails, the file was renamed and the original no longer exists, so return a success status
+ return true;
}
- return true;
}
catch(...){
return false;
@@ -1567,18 +1922,16 @@ inline bool unlink_file(const char *filename)
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){}
+ hkey key_;
+ reg_closer(hkey key) : key_(key){}
~reg_closer(){ reg_close_key(key_); }
};
inline void get_shared_documents_folder(std::string &s)
{
+ #if 1 //Original registry search code
s.clear();
- void *key;
+ hkey key;
if (reg_open_key_ex( hkey_local_machine
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
, 0
@@ -1602,12 +1955,24 @@ inline void get_shared_documents_folder(std::string &s)
(void)err;
}
}
+ #else //registry alternative: SHGetSpecialFolderPathA
+ const int BIPC_CSIDL_COMMON_APPDATA = 0x0023; // All Users\Application Data
+ const int BIPC_CSIDL_FLAG_CREATE = 0x8000; // new for Win2K, or this in to force creation of folder
+ const int BIPC_SHGFP_TYPE_CURRENT = 0; // current value for user, verify it exists
+
+ s.clear();
+ char szPath[max_path];
+ if(0 == SHGetFolderPathA(0, BIPC_CSIDL_COMMON_APPDATA | BIPC_CSIDL_FLAG_CREATE, 0, BIPC_SHGFP_TYPE_CURRENT, szPath)){
+ s = szPath;
+ }
+
+ #endif
}
inline void get_registry_value(const char *folder, const char *value_key, std::vector<unsigned char> &s)
{
s.clear();
- void *key;
+ hkey key;
if (reg_open_key_ex( hkey_local_machine
, folder
, 0
@@ -1700,7 +2065,7 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_
IWbemServices_BIPC *pWbemServices = 0;
if( 0 != pIWbemLocator->ConnectServer(
- bstrNamespace, // Namespace
+ (bstr)bstrNamespace, // Namespace
0, // Userid
0, // PW
0, // Locale
@@ -1738,8 +2103,8 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_
IEnumWbemClassObject_BIPC * pEnumObject = 0;
if ( 0 != pWbemServices->ExecQuery(
- L"WQL",
- strValue.c_str(),
+ (bstr)L"WQL",
+ (bstr)strValue.c_str(),
//WBEM_FLAG_RETURN_IMMEDIATELY_BIPC,
WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC | WBEM_FLAG_FORWARD_ONLY_BIPC,
0,
@@ -1762,9 +2127,9 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_
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 ) ){
+ if ( 0 == pClassObject->Get( (bstr)L"LastBootUpTime", 0, &vwchar, 0, 0 ) ){
bRet = true;
- strValue = vwchar.value.pbstrVal;
+ strValue = (wchar_t*)vwchar.bstrVal;
VariantClear(&vwchar );
break;
}
@@ -1773,6 +2138,10 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_
return bRet;
}
+#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME
+
+//Obtains the bootup time from WMI LastBootUpTime.
+//This time seems to change with hibernation and clock synchronization so avoid it.
inline bool get_last_bootup_time( std::wstring& strValue )
{
bool ret = get_wmi_class_attribute(strValue, L"Win32_OperatingSystem", L"LastBootUpTime");
@@ -1798,12 +2167,110 @@ inline bool get_last_bootup_time( std::string& str )
return ret;
}
+#else
+
+// Loop through the buffer and obtain the contents of the
+// requested record in the buffer.
+inline bool find_record_in_buffer( const void* pBuffer, unsigned long dwBytesRead, const char *provider_name
+ , unsigned int id_to_find, interprocess_eventlogrecord *&pevent_log_record)
+{
+ const unsigned char * pRecord = static_cast<const unsigned char*>(pBuffer);
+ const unsigned char * pEndOfRecords = pRecord + dwBytesRead;
+
+ while (pRecord < pEndOfRecords){
+ interprocess_eventlogrecord *pTypedRecord = (interprocess_eventlogrecord*)pRecord;
+ // Check provider, written at the end of the fixed-part of the record
+ if (0 == std::strcmp(provider_name, (char*)(pRecord + sizeof(interprocess_eventlogrecord))))
+ {
+ // Check event id
+ if(id_to_find == (pTypedRecord->EventID & 0xFFFF)){
+ pevent_log_record = pTypedRecord;
+ return true;
+ }
+ }
+
+ pRecord += pTypedRecord->Length;
+ }
+ pevent_log_record = 0;
+ return false;
+}
+
+//Obtains the bootup time from the System Event Log,
+//event ID == 6005 (event log started).
+//Adapted from http://msdn.microsoft.com/en-us/library/windows/desktop/bb427356.aspx
+inline bool get_last_bootup_time(std::string &stamp)
+{
+ const char *source_name = "System";
+ const char *provider_name = "EventLog";
+ const unsigned short event_id = 6005u;
+
+ unsigned long status = 0;
+ unsigned long dwBytesToRead = 0;
+ unsigned long dwBytesRead = 0;
+ unsigned long dwMinimumBytesToRead = 0;
+
+ // The source name (provider) must exist as a subkey of Application.
+ void *hEventLog = OpenEventLogA(0, source_name);
+ if (hEventLog){
+ eventlog_handle_closer hnd_closer(hEventLog); (void)hnd_closer;
+ // Allocate an initial block of memory used to read event records. The number
+ // of records read into the buffer will vary depending on the size of each event.
+ // The size of each event will vary based on the size of the user-defined
+ // data included with each event, the number and length of insertion
+ // strings, and other data appended to the end of the event record.
+ dwBytesToRead = max_record_buffer_size;
+ c_heap_deleter heap_deleter(dwBytesToRead);
+
+ // Read blocks of records until you reach the end of the log or an
+ // error occurs. The records are read from newest to oldest. If the buffer
+ // is not big enough to hold a complete event record, reallocate the buffer.
+ if (heap_deleter.get() != 0){
+ while (0 == status){
+ if (!ReadEventLogA(hEventLog,
+ eventlog_sequential_read | eventlog_backwards_read,
+ 0,
+ heap_deleter.get(),
+ dwBytesToRead,
+ &dwBytesRead,
+ &dwMinimumBytesToRead)) {
+ status = get_last_error();
+ if (error_insufficient_buffer == status) {
+ status = 0;
+ dwBytesToRead = dwMinimumBytesToRead;
+ heap_deleter.realloc_mem(dwMinimumBytesToRead);
+ if (!heap_deleter.get()){
+ return false;
+ }
+ }
+ else{ //Not found or EOF
+ return false;
+ }
+ }
+ else
+ {
+ interprocess_eventlogrecord *pTypedRecord;
+ // Print the contents of each record in the buffer.
+ if(find_record_in_buffer(heap_deleter.get(), dwBytesRead, provider_name, event_id, pTypedRecord)){
+ char stamp_str[sizeof(unsigned long)*3+1];
+ std::sprintf(&stamp_str[0], "%u", ((unsigned int)pTypedRecord->TimeGenerated));
+ stamp = stamp_str;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+#endif
+
inline bool is_directory(const char *path)
{
- unsigned long attrib = GetFileAttributesA(path);
+ unsigned long attrib = GetFileAttributesA(path);
- return (attrib != invalid_file_attributes &&
- (attrib & file_attribute_directory));
+ return (attrib != invalid_file_attributes &&
+ (attrib & file_attribute_directory));
}
inline bool get_file_mapping_size(void *file_mapping_hnd, __int64 &size)
@@ -1814,11 +2281,8 @@ inline bool get_file_mapping_size(void *file_mapping_hnd, __int64 &size)
interprocess_section_basic_information info;
unsigned long ntstatus =
pNtQuerySection(file_mapping_hnd, section_basic_information, &info, sizeof(info), 0);
- if(ntstatus){
- return false;
- }
size = info.section_size;
- return true;
+ return !ntstatus;
}
inline bool get_semaphore_info(void *handle, long &count, long &limit)
@@ -1828,14 +2292,41 @@ inline bool get_semaphore_info(void *handle, long &count, long &limit)
(winapi::NtQuerySemaphore_t)dll_func::get(winapi::dll_func::NtQuerySemaphore);
unsigned int ret_len;
long status = pNtQuerySemaphore(handle, winapi::semaphore_basic_information, &info, sizeof(info), &ret_len);
- if(status){
- return false;
- }
count = info.count;
limit = info.limit;
- return true;
+ return !status;
+}
+
+inline bool query_timer_resolution(unsigned long *lowres, unsigned long *highres, unsigned long *curres)
+{
+ winapi::NtQueryTimerResolution_t pNtQueryTimerResolution =
+ (winapi::NtQueryTimerResolution_t)dll_func::get(winapi::dll_func::NtQueryTimerResolution);
+ return !pNtQueryTimerResolution(lowres, highres, curres);
+}
+
+inline bool set_timer_resolution(unsigned long RequestedResolution, int Set, unsigned long* ActualResolution)
+{
+ winapi::NtSetTimerResolution_t pNtSetTimerResolution =
+ (winapi::NtSetTimerResolution_t)dll_func::get(winapi::dll_func::NtSetTimerResolution);
+ return !pNtSetTimerResolution(RequestedResolution, Set, ActualResolution);
+}
+
+inline bool query_performance_counter(__int64 *lpPerformanceCount)
+{
+ QueryPerformanceCounter_t pQueryPerformanceCounter = (QueryPerformanceCounter_t)
+ dll_func::get(dll_func::QueryPerformanceCounter);
+ return 0 != pQueryPerformanceCounter(lpPerformanceCount);
+}
+
+inline bool query_performance_frequency(__int64 *lpFrequency)
+{
+ QueryPerformanceCounter_t pQueryPerformanceFrequency = (QueryPerformanceFrequency_t)
+ dll_func::get(dll_func::QueryPerformanceFrequency);
+ return 0 != pQueryPerformanceFrequency(lpFrequency);
}
+inline unsigned long get_tick_count()
+{ return GetTickCount(); }
} //namespace winapi
} //namespace interprocess
@@ -1843,4 +2334,4 @@ inline bool get_semaphore_info(void *handle, long &count, long &limit)
#include <boost/interprocess/detail/config_end.hpp>
-#endif //#ifdef BOOST_INTERPROCESS_WIN32_PRIMITIVES_HPP
+#endif //#ifdef BOOST_INTERPROCESS_WIN32_API_HPP
diff --git a/boost/interprocess/detail/windows_intermodule_singleton.hpp b/boost/interprocess/detail/windows_intermodule_singleton.hpp
index a716e270a7..58102689da 100644
--- a/boost/interprocess/detail/windows_intermodule_singleton.hpp
+++ b/boost/interprocess/detail/windows_intermodule_singleton.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,12 +11,13 @@
#ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
#define BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
-#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/container/string.hpp>
#if !defined(BOOST_INTERPROCESS_WINDOWS)
#error "This header can't be included from non-windows operating systems"
@@ -29,7 +30,7 @@
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/cstdint.hpp>
#include <string>
-#include <map>
+#include <boost/container/map.hpp>
namespace boost{
namespace interprocess{
@@ -49,7 +50,7 @@ namespace intermodule_singleton_helpers {
// max and current semaphore count.
class windows_semaphore_based_map
{
- typedef std::map<std::string, ref_count_ptr> map_type;
+ typedef boost::container::map<boost::container::string, ref_count_ptr> map_type;
public:
windows_semaphore_based_map()
@@ -68,8 +69,8 @@ class windows_semaphore_based_map
//in max_count and initial count parameters.
//Also, max count must be bigger than 0 and bigger or equal than initial count.
if(sizeof(void*) == sizeof(boost::uint32_t)){
- //This means that for 32 bit processes, a semaphore count (31 usable bits) is
- //enough to store 4 byte aligned memory (4GB -> 32 bits - 2 bits = 30 bits).
+ //This means that for 32 bit processes, a semaphore count (31 usable bits) is
+ //enough to store 4 byte aligned memory (4GB -> 32 bits - 2 bits = 30 bits).
//The max count will hold the pointer value and current semaphore count
//will be zero.
//
@@ -135,6 +136,7 @@ class windows_semaphore_based_map
success = success && m_sem_map.open_or_create
(name.c_str(), initial_count, max_count, perm, created);
if(!success){
+ delete m;
//winapi_xxx wrappers do the cleanup...
throw int(0);
}
@@ -181,7 +183,7 @@ class windows_semaphore_based_map
{
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
map_type &map = this->get_map_unlocked();
- map_type::iterator it = map.find(std::string(name));
+ map_type::iterator it = map.find(boost::container::string(name));
if(it != map.end()){
return &it->second;
}
@@ -194,7 +196,7 @@ class windows_semaphore_based_map
{
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
map_type &map = this->get_map_unlocked();
- map_type::iterator it = map.insert(map_type::value_type(std::string(name), ref)).first;
+ map_type::iterator it = map.insert(map_type::value_type(boost::container::string(name), ref)).first;
return &it->second;
}
@@ -202,7 +204,7 @@ class windows_semaphore_based_map
{
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
map_type &map = this->get_map_unlocked();
- return map.erase(std::string(name)) != 0;
+ return map.erase(boost::container::string(name)) != 0;
}
template<class F>
@@ -217,14 +219,16 @@ class windows_semaphore_based_map
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
m_sem_count.wait();
if(0 == m_sem_count.value()){
- delete &this->get_map_unlocked();
+ map_type &map = this->get_map_unlocked();
+ BOOST_ASSERT(map.empty());
+ delete &map;
}
//First close sems to protect this with the external mutex
m_sem_map.close();
m_sem_count.close();
//Once scoped_lock unlocks the mutex, the destructor will close the handle...
}
-
+
private:
winapi_mutex_wrapper m_mtx_lock;
winapi_semaphore_wrapper m_sem_map;
@@ -287,7 +291,7 @@ struct thread_safe_global_map_dependant<windows_semaphore_based_map>
} //namespace intermodule_singleton_helpers {
-template<typename C, bool LazyInit = true, bool Phoenix = true>
+template<typename C, bool LazyInit = true, bool Phoenix = false>
class windows_intermodule_singleton
: public intermodule_singleton_impl
< C
diff --git a/boost/interprocess/detail/workaround.hpp b/boost/interprocess/detail/workaround.hpp
index 884b8680a6..d0456b5053 100644
--- a/boost/interprocess/detail/workaround.hpp
+++ b/boost/interprocess/detail/workaround.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,23 +11,46 @@
#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
#define BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#define BOOST_INTERPROCESS_WINDOWS
#define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION
#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
+ //Define this to connect with shared memory created with versions < 1.54
+ //#define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME
#else
#include <unistd.h>
#if defined(_POSIX_THREAD_PROCESS_SHARED) && ((_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__)
+ #if defined(__CYGWIN__)
+ #define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED
+ //Mac Os X < Lion (10.7) might define _POSIX_THREAD_PROCESS_SHARED but there is no real support.
+ #elif defined(__APPLE__)
+ #include "TargetConditionals.h"
+ //Check we're on Mac OS target
+ #if defined(TARGET_OS_MAC)
+ #include "AvailabilityMacros.h"
+ //If minimum target for this compilation is older than Mac Os Lion, then we are out of luck
+ #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
+ #define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED
+ #endif
+ #endif
+ #endif
+
+ //If buggy _POSIX_THREAD_PROCESS_SHARED is detected avoid using it
+ #if defined(BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED)
+ #undef BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED
+ #else
#define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
#endif
#endif
-
+
#if defined(_POSIX_BARRIERS) && ((_POSIX_BARRIERS - 0) > 0)
#define BOOST_INTERPROCESS_POSIX_BARRIERS
#endif
@@ -39,22 +62,22 @@
#endif
//Some platforms have a limited (name length) named semaphore support
#elif (defined(__FreeBSD__) && (__FreeBSD__ >= 4)) || defined(__APPLE__)
- #define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
+ #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))
+ #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
#endif
//Check for XSI shared memory objects. They are available in nearly all UNIX platforms
- #if !defined(__QNXNTO__)
+ #if !defined(__QNXNTO__) && !defined(__ANDROID__)
#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
#endif
@@ -90,6 +113,8 @@
// hp-ux tru64 vms freebsd
#if defined(__hpux) || defined(__osf__) || defined(__vms) || (defined(__FreeBSD__) && (__FreeBSD__ < 7))
#define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
+ //Some systems have "jailed" environments where shm usage is restricted at runtime
+ //and temporary file file based shm is possible in those executions.
#elif defined(__FreeBSD__)
#define BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
#endif
@@ -108,6 +133,10 @@
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
#define BOOST_INTERPROCESS_BSD_DERIVATIVE
+ //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas
+ //others (FreeBSD & Darwin) need sys/types.h
+ #include <sys/types.h>
+ #include <sys/param.h>
#include <sys/sysctl.h>
#if defined(CTL_KERN) && defined (KERN_BOOTTIME)
//#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
@@ -115,7 +144,7 @@
#endif
#endif //!defined(BOOST_INTERPROCESS_WINDOWS)
-#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif
@@ -130,6 +159,44 @@
#define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000
#endif
+//Other switches
+//BOOST_INTERPROCESS_MSG_QUEUE_USES_CIRC_INDEX
+//message queue uses a circular queue as index instead of an array (better performance)
+//Boost version < 1.52 uses an array, so undef this if you want to communicate
+//with processes compiled with those versions.
+#define BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
+
+//Inline attributes
+#if defined(_MSC_VER)
+ #define BOOST_INTERPROCESS_ALWAYS_INLINE __forceinline
+#elif defined (__GNUC__)
+ #define BOOST_INTERPROCESS_ALWAYS_INLINE __attribute__((__always_inline__))
+#else
+ #define BOOST_INTERPROCESS_ALWAYS_INLINE inline
+#endif
+
+#if defined(_MSC_VER)
+ #define BOOST_INTERPROCESS_NEVER_INLINE __declspec(noinline)
+#elif defined (__GNUC__)
+ #define BOOST_INTERPROCESS_NEVER_INLINE __attribute__((__noinline__))
+#endif
+
+//Macros for documentation purposes. For code, expands to the argument
+#define BOOST_INTERPROCESS_IMPDEF(TYPE) TYPE
+#define BOOST_INTERPROCESS_SEEDOC(TYPE) TYPE
+
+#if defined(BOOST_NO_CXX11_NOEXCEPT)
+ #if defined(BOOST_MSVC)
+ #define BOOST_INTERPROCESS_NOEXCEPT throw()
+ #else
+ #define BOOST_INTERPROCESS_NOEXCEPT
+ #endif
+ #define BOOST_INTERPROCESS_NOEXCEPT_IF(x)
+#else
+ #define BOOST_INTERPROCESS_NOEXCEPT noexcept
+ #define BOOST_INTERPROCESS_NOEXCEPT_IF(x) noexcept(x)
+#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
index ef4b009bc1..5bb077179a 100644
--- a/boost/interprocess/detail/xsi_shared_memory_device.hpp
+++ b/boost/interprocess/detail/xsi_shared_memory_device.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP
#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/detail/workaround.hpp>
@@ -23,7 +27,7 @@
#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/detail/shared_dir_helpers.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -44,9 +48,9 @@ namespace interprocess {
class xsi_shared_memory_device
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
@@ -74,10 +78,10 @@ class xsi_shared_memory_device
{ 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;
+ return *this;
}
//!Swaps two xsi_shared_memory_device. Does not throw
@@ -113,7 +117,7 @@ class xsi_shared_memory_device
//!Returns false on error. Never throws
static bool remove(int shmid);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
template<int Dummy>
struct info_constants_t
@@ -147,7 +151,7 @@ class xsi_shared_memory_device
xsi_shared_memory m_shm;
mode_t m_mode;
std::string m_name;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
template<int Dummy>
@@ -162,7 +166,7 @@ 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
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline xsi_shared_memory_device::xsi_shared_memory_device()
: m_shm(), m_mode(invalid_mode), m_name()
@@ -178,7 +182,7 @@ 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);
+ m_name.swap(other.m_name);
}
inline mapping_handle_t xsi_shared_memory_device::get_mapping_handle() const
@@ -197,7 +201,7 @@ inline void xsi_shared_memory_device::priv_obtain_index
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_shared_dir_cleaning_old_and_get_filepath(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);
@@ -382,7 +386,7 @@ inline bool xsi_shared_memory_device::remove(const char *shmname)
inline bool xsi_shared_memory_device::remove(int shmid)
{ return xsi_shared_memory::remove(shmid); }
-///@endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp b/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp
index 14811e7e62..d1c71d55f5 100644
--- a/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp
+++ b/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP
#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/detail/workaround.hpp>
@@ -23,7 +27,7 @@
#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/detail/shared_dir_helpers.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -38,22 +42,22 @@ namespace interprocess {
class xsi_shared_memory_file_wrapper
: public xsi_shared_memory
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
xsi_shared_memory_file_wrapper() : xsi_shared_memory() {}
- xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions())
+ xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t , std::size_t size, const permissions& perm = permissions())
: xsi_shared_memory(create_only_t(), key, size, perm.get_permissions())
{}
- xsi_shared_memory_file_wrapper(open_or_create_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions())
+ xsi_shared_memory_file_wrapper(open_or_create_t, const xsi_key &key, mode_t , std::size_t size, const permissions& perm = permissions())
: xsi_shared_memory(open_or_create_t(), key, size, perm.get_permissions())
{}
- xsi_shared_memory_file_wrapper(open_only_t, const xsi_key &key, mode_t mode, const permissions& perm = permissions())
+ xsi_shared_memory_file_wrapper(open_only_t, const xsi_key &key, mode_t, const permissions& = permissions())
: xsi_shared_memory(open_only_t(), key)
{}
@@ -61,10 +65,10 @@ class xsi_shared_memory_file_wrapper
{ 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;
+ return *this;
}
//!Swaps two xsi_shared_memory_file_wrapper. Does not throw
diff --git a/boost/interprocess/errors.hpp b/boost/interprocess/errors.hpp
index 9eed55a29b..6d4572f718 100644
--- a/boost/interprocess/errors.hpp
+++ b/boost/interprocess/errors.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -24,7 +24,7 @@
#ifndef BOOST_INTERPROCESS_ERRORS_HPP
#define BOOST_INTERPROCESS_ERRORS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -33,7 +33,7 @@
#include <stdarg.h>
#include <string>
-#if (defined BOOST_INTERPROCESS_WINDOWS)
+#if defined (BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
@@ -42,17 +42,17 @@
# else //ifdef BOOST_HAS_UNISTD_H
# error Unknown platform
# endif //ifdef BOOST_HAS_UNISTD_H
-#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
+#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
//!\file
//!Describes the error numbering of interprocess classes
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline int system_error_code() // artifact of POSIX and WINDOWS error reporting
{
- #if (defined BOOST_INTERPROCESS_WINDOWS)
+ #if defined (BOOST_INTERPROCESS_WINDOWS)
return winapi::get_last_error();
#else
return errno; // GCC 3.1 won't accept ::errno
@@ -60,7 +60,7 @@ inline int system_error_code() // artifact of POSIX and WINDOWS error reporting
}
-#if (defined BOOST_INTERPROCESS_WINDOWS)
+#if defined (BOOST_INTERPROCESS_WINDOWS)
inline void fill_system_message(int sys_err_code, std::string &str)
{
void *lpMsgBuf;
@@ -85,7 +85,7 @@ inline void fill_system_message(int sys_err_code, std::string &str)
inline void fill_system_message( int system_error, std::string &str)
{ str = std::strerror(system_error); }
# endif
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
enum error_code_t
{
@@ -115,11 +115,12 @@ enum error_code_t
invalid_argument,
timeout_when_locking_error,
timeout_when_waiting_error,
+ owner_dead_error
};
typedef int native_error_t;
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
struct ec_xlate
{
native_error_t sys_ec;
@@ -128,7 +129,7 @@ struct ec_xlate
static const ec_xlate ec_table[] =
{
- #if (defined BOOST_INTERPROCESS_WINDOWS)
+ #if defined (BOOST_INTERPROCESS_WINDOWS)
{ /*ERROR_ACCESS_DENIED*/5L, security_error },
{ /*ERROR_INVALID_ACCESS*/12L, security_error },
{ /*ERROR_SHARING_VIOLATION*/32L, security_error },
@@ -161,7 +162,7 @@ static const ec_xlate ec_table[] =
{ /*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)
+ #else //#if defined (BOOST_INTERPROCESS_WINDOWS)
{ EACCES, security_error },
{ EROFS, read_only_error },
{ EIO, io_error },
@@ -179,11 +180,11 @@ static const ec_xlate ec_table[] =
{ EMFILE, out_of_resource_error },
{ ENOENT, not_such_file_or_directory },
{ EINVAL, invalid_argument }
- #endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
+ #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 ){
@@ -226,7 +227,7 @@ struct error_info
native_error_t m_nat;
error_code_t m_ec;
};
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} // namespace interprocess {
} // namespace boost
diff --git a/boost/interprocess/exceptions.hpp b/boost/interprocess/exceptions.hpp
index a4f196f0be..36e5e2ca5b 100644
--- a/boost/interprocess/exceptions.hpp
+++ b/boost/interprocess/exceptions.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_EXCEPTIONS_HPP
#define BOOST_INTERPROCESS_EXCEPTIONS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -75,11 +75,11 @@ class interprocess_exception : public std::exception
// 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
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
error_info m_err;
std::string m_str;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!This is the exception thrown by shared interprocess_mutex family when a deadlock situation
diff --git a/boost/interprocess/file_mapping.hpp b/boost/interprocess/file_mapping.hpp
index 2a4e4cca00..935260354f 100644
--- a/boost/interprocess/file_mapping.hpp
+++ b/boost/interprocess/file_mapping.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_FILE_MAPPING_HPP
#define BOOST_INTERPROCESS_FILE_MAPPING_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -19,7 +23,7 @@
#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 <boost/move/utility_core.hpp>
#include <string> //std::string
//!\file
@@ -32,9 +36,9 @@ namespace interprocess {
//!create mapped regions from the mapped files
class file_mapping
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
BOOST_MOVABLE_BUT_NOT_COPYABLE(file_mapping)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructs an empty file mapping.
@@ -52,6 +56,7 @@ class file_mapping
//!Does not throw
file_mapping(BOOST_RV_REF(file_mapping) moved)
: m_handle(file_handle_t(ipcdetail::invalid_file()))
+ , m_mode(read_only)
{ this->swap(moved); }
//!Moves the ownership of "moved"'s file mapping to *this.
@@ -61,7 +66,7 @@ class file_mapping
{
file_mapping tmp(boost::move(moved));
this->swap(tmp);
- return *this;
+ return *this;
}
//!Swaps to file_mappings.
@@ -90,18 +95,19 @@ class file_mapping
//!being used other processes and no deletion permission was shared.
static bool remove(const char *filename);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
//!Closes a previously opened file mapping. Never throws.
void priv_close();
file_handle_t m_handle;
- mode_t m_mode;
- std::string m_filename;
- /// @endcond
+ mode_t m_mode;
+ std::string m_filename;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
inline file_mapping::file_mapping()
: m_handle(file_handle_t(ipcdetail::invalid_file()))
+ , m_mode(read_only)
{}
inline file_mapping::~file_mapping()
@@ -111,10 +117,10 @@ 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);
+ m_filename.swap(other.m_filename);
}
inline mapping_handle_t file_mapping::get_mapping_handle() const
@@ -148,7 +154,7 @@ inline file_mapping::file_mapping
inline bool file_mapping::remove(const char *filename)
{ return ipcdetail::delete_file(filename); }
-///@cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void file_mapping::priv_close()
{
@@ -158,8 +164,6 @@ inline void file_mapping::priv_close()
}
}
-///@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
@@ -176,6 +180,8 @@ class remove_file_on_destroy
{ ipcdetail::delete_file(m_name); }
};
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/indexes/flat_map_index.hpp b/boost/interprocess/indexes/flat_map_index.hpp
index bac387e268..4307dedb0e 100644
--- a/boost/interprocess/indexes/flat_map_index.hpp
+++ b/boost/interprocess/indexes/flat_map_index.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -10,6 +10,10 @@
#ifndef BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP
#define BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -25,6 +29,8 @@
//[flat_map_index
namespace boost { namespace interprocess {
+#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
//!Helper class to define typedefs from IndexTraits
template <class MapConfig>
struct flat_map_index_aux
@@ -41,6 +47,8 @@ struct flat_map_index_aux
key_less, allocator_type> index_t;
};
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
//!Index type based in flat_map. Just derives from flat_map and
//!defines the interface needed by managed memory segments.
template <class MapConfig>
@@ -48,12 +56,12 @@ class flat_map_index
//Derive class from flat_map specialization
: public flat_map_index_aux<MapConfig>::index_t
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
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
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor. Takes a pointer to the segment manager. Can throw
diff --git a/boost/interprocess/indexes/iset_index.hpp b/boost/interprocess/indexes/iset_index.hpp
index 8fc91466f3..170e5dac1b 100644
--- a/boost/interprocess/indexes/iset_index.hpp
+++ b/boost/interprocess/indexes/iset_index.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_ISET_INDEX_HPP
#define BOOST_INTERPROCESS_ISET_INDEX_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -28,7 +32,7 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Helper class to define typedefs from IndexTraits
template <class MapConfig>
@@ -52,7 +56,7 @@ struct iset_index_aux
, bi::base_hook<derivation_hook>
>::type index_t;
};
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Index type based in boost::intrusive::set.
//!Just derives from boost::intrusive::set
@@ -62,13 +66,13 @@ class iset_index
//Derive class from map specialization
: public iset_index_aux<MapConfig>::index_t
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef iset_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t index_type;
typedef typename MapConfig::
intrusive_compare_key_type intrusive_compare_key_type;
typedef typename MapConfig::char_type char_type;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
typedef typename index_type::iterator iterator;
@@ -76,13 +80,13 @@ class iset_index
typedef typename index_type::insert_commit_data insert_commit_data;
typedef typename index_type::value_type value_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
struct intrusive_key_value_less
{
bool operator()(const intrusive_compare_key_type &i, const value_type &b) const
- {
+ {
std::size_t blen = b.name_length();
return (i.m_len < blen) ||
(i.m_len == blen &&
@@ -91,7 +95,7 @@ class iset_index
}
bool operator()(const value_type &b, const intrusive_compare_key_type &i) const
- {
+ {
std::size_t blen = b.name_length();
return (blen < i.m_len) ||
(blen == i.m_len &&
@@ -100,7 +104,7 @@ class iset_index
}
};
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
@@ -130,7 +134,7 @@ class iset_index
{ return index_type::insert_check(key, intrusive_key_value_less(), commit_data); }
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Trait class to detect if an index is an intrusive
//!index.
@@ -140,7 +144,7 @@ struct is_intrusive_index
{
static const bool value = true;
};
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost
diff --git a/boost/interprocess/indexes/iunordered_set_index.hpp b/boost/interprocess/indexes/iunordered_set_index.hpp
index 3c5f85526c..c85c557c25 100644
--- a/boost/interprocess/indexes/iunordered_set_index.hpp
+++ b/boost/interprocess/indexes/iunordered_set_index.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP
#define BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -28,7 +32,7 @@
namespace boost { namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Helper class to define typedefs
//!from IndexTraits
@@ -58,21 +62,21 @@ struct iunordered_set_index_aux
struct equal_function
{
bool operator()(const intrusive_compare_key_type &i, const value_type &b) const
- {
+ {
return (i.m_len == b.name_length()) &&
(std::char_traits<char_type>::compare
(i.mp_str, b.name(), i.m_len) == 0);
}
bool operator()(const value_type &b, const intrusive_compare_key_type &i) const
- {
+ {
return (i.m_len == b.name_length()) &&
(std::char_traits<char_type>::compare
(i.mp_str, b.name(), i.m_len) == 0);
}
bool operator()(const value_type &b1, const value_type &b2) const
- {
+ {
return (b1.name_length() == b2.name_length()) &&
(std::char_traits<char_type>::compare
(b1.name(), b2.name(), b1.name_length()) == 0);
@@ -116,7 +120,7 @@ struct iunordered_set_index_aux
bucket_type init_bucket;
};
};
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Index type based in boost::intrusive::set.
//!Just derives from boost::intrusive::set
@@ -127,7 +131,7 @@ class iunordered_set_index
: private iunordered_set_index_aux<MapConfig>::allocator_holder
, public iunordered_set_index_aux<MapConfig>::index_t
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef iunordered_set_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t index_type;
typedef typename MapConfig::
@@ -139,7 +143,7 @@ class iunordered_set_index
iunordered_set_index_aux<MapConfig>::allocator_type allocator_type;
typedef typename
iunordered_set_index_aux<MapConfig>::allocator_holder allocator_holder;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
typedef typename index_type::iterator iterator;
@@ -151,7 +155,7 @@ class iunordered_set_index
typedef typename index_type::bucket_traits bucket_traits;
typedef typename index_type::size_type size_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef typename index_aux::
segment_manager_base segment_manager_base;
@@ -190,7 +194,7 @@ class iunordered_set_index
bucket_ptr shunk_p = alloc.allocation_command
(boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, received_size, received_size, received_size, buckets).first;
- BOOST_ASSERT(buckets == shunk_p);
+ BOOST_ASSERT(buckets == shunk_p); (void)shunk_p;
bucket_ptr buckets_init = buckets + received_size;
for(size_type i = 0; i < (old_size - received_size); ++i){
@@ -236,7 +240,7 @@ class iunordered_set_index
iunordered_set_index<MapConfig>* get_this_pointer()
{ return this; }
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor. Takes a pointer to the
@@ -290,7 +294,7 @@ class iunordered_set_index
size_type cur_size = this->size();
size_type cur_count = this->bucket_count();
bucket_ptr old_p = this->bucket_pointer();
-
+
if(!this->size() && old_p != bucket_ptr(&this->init_bucket)){
this->rehash(bucket_traits(bucket_ptr(&this->init_bucket), 1));
destroy_buckets(this->alloc, old_p, cur_count);
@@ -337,7 +341,7 @@ class iunordered_set_index
//Strong guarantee: if something goes wrong
//we should remove the insertion.
//
- //We can use the iterator because the hash function
+ //We can use the iterator because the hash function
//can't throw and this means that "reserve" will
//throw only because of the memory allocation:
//the iterator has not been invalidated.
@@ -349,7 +353,7 @@ class iunordered_set_index
}
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Trait class to detect if an index is an intrusive
//!index
@@ -359,7 +363,7 @@ struct is_intrusive_index
{
static const bool value = true;
};
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
}} //namespace boost { namespace interprocess {
diff --git a/boost/interprocess/indexes/map_index.hpp b/boost/interprocess/indexes/map_index.hpp
index 1bfc7ce310..a744e9000e 100644
--- a/boost/interprocess/indexes/map_index.hpp
+++ b/boost/interprocess/indexes/map_index.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_MAP_INDEX_HPP
#define BOOST_INTERPROCESS_MAP_INDEX_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -55,12 +59,12 @@ class map_index
//Derive class from map specialization
: public ipcdetail::map_index_aux<MapConfig>::index_t
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef ipcdetail::map_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t base_type;
typedef typename MapConfig::
segment_manager_base segment_manager_base;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor. Takes a pointer to the
@@ -80,7 +84,7 @@ class map_index
{ base_type::get_stored_allocator().deallocate_free_blocks(); }
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Trait class to detect if an index is a node
//!index. This allows more efficient operations
@@ -91,7 +95,7 @@ struct is_node_index
{
static const bool value = true;
};
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
}} //namespace boost { namespace interprocess {
diff --git a/boost/interprocess/indexes/null_index.hpp b/boost/interprocess/indexes/null_index.hpp
index a0353b101c..d0e026b896 100644
--- a/boost/interprocess/indexes/null_index.hpp
+++ b/boost/interprocess/indexes/null_index.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -10,6 +10,10 @@
#ifndef BOOST_INTERPROCESS_NULL_INDEX_HPP
#define BOOST_INTERPROCESS_NULL_INDEX_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -28,14 +32,14 @@ namespace interprocess {
template <class MapConfig>
class null_index
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef typename MapConfig::
segment_manager_base segment_manager_base;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
- typedef void * iterator;
- typedef const void * const_iterator;
+ typedef int * iterator;
+ typedef const int * const_iterator;
//!begin() is equal
//!to end()
diff --git a/boost/interprocess/indexes/unordered_map_index.hpp b/boost/interprocess/indexes/unordered_map_index.hpp
index 7cf4b85e65..f40d970819 100644
--- a/boost/interprocess/indexes/unordered_map_index.hpp
+++ b/boost/interprocess/indexes/unordered_map_index.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP
#define BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -27,7 +31,7 @@
namespace boost {
namespace interprocess {
-///@cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Helper class to define typedefs from
//!IndexTraits
@@ -57,7 +61,7 @@ struct unordered_map_index_aux
key_equal, allocator_type> index_t;
};
-///@endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Index type based in unordered_map. Just derives from unordered_map and
//!defines the interface needed by managed memory segments
@@ -66,12 +70,12 @@ class unordered_map_index
//Derive class from unordered_map specialization
: public unordered_map_index_aux<MapConfig>::index_t
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef unordered_map_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t base_type;
typedef typename
MapConfig::segment_manager_base segment_manager_base;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor. Takes a pointer to the
@@ -93,7 +97,7 @@ class unordered_map_index
{ base_type::rehash(base_type::size()); }
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Trait class to detect if an index is a node
//!index. This allows more efficient operations
@@ -104,7 +108,7 @@ struct is_node_index
{
static const bool value = true;
};
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
}} //namespace boost { namespace interprocess {
diff --git a/boost/interprocess/interprocess_fwd.hpp b/boost/interprocess/interprocess_fwd.hpp
index 68fd89fb91..6c9675b401 100644
--- a/boost/interprocess/interprocess_fwd.hpp
+++ b/boost/interprocess/interprocess_fwd.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,21 +11,118 @@
#ifndef BOOST_INTERPROCESS_FWD_HPP
#define BOOST_INTERPROCESS_FWD_HPP
-#if defined (_MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
+//! \file
+//! This header file forward declares the basic interprocess types:
+//! - boost::interprocess::offset_ptr;
+//! - boost::interprocess::permissions;
+//! - boost::interprocess::mapped_region;
+//! - boost::interprocess::file_mapping;
+//! - boost::interprocess::shared_memory_object;
+//! - boost::interprocess::windows_shared_memory;
+//! - boost::interprocess::xsi_shared_memory;
+//!
+//! The following synchronization mechanisms and locks:
+//! - boost::interprocess::null_mutex;
+//! - boost::interprocess::interprocess_mutex;
+//! - boost::interprocess::interprocess_recursive_mutex;
+//! - boost::interprocess::interprocess_semaphore;
+//! - boost::interprocess::named_mutex;
+//! - boost::interprocess::named_recursive_mutex;
+//! - boost::interprocess::named_semaphore;
+//! - boost::interprocess::interprocess_sharable_mutex;
+//! - boost::interprocess::interprocess_condition;
+//! - boost::interprocess::scoped_lock;
+//! - boost::interprocess::sharable_lock;
+//! - boost::interprocess::upgradable_lock;
+//!
+//! The following mutex families:
+//! - boost::interprocess::mutex_family;
+//! - boost::interprocess::null_mutex_family;
+//!
+//! The following allocators:
+//! - boost::interprocess::allocator;
+//! - boost::interprocess::node_allocator;
+//! - boost::interprocess::private_node_allocator;
+//! - boost::interprocess::cached_node_allocator;
+//! - boost::interprocess::adaptive_pool;
+//! - boost::interprocess::private_adaptive_pool;
+//! - boost::interprocess::cached_adaptive_pool;
+//!
+//! The following allocation algorithms:
+//! - boost::interprocess::simple_seq_fit;
+//! - boost::interprocess::rbtree_best_fit;
+//!
+//! The following index types:
+//! - boost::interprocess::flat_map_index;
+//! - boost::interprocess::iset_index;
+//! - boost::interprocess::iunordered_set_index;
+//! - boost::interprocess::map_index;
+//! - boost::interprocess::null_index;
+//! - boost::interprocess::unordered_map_index;
+//!
+//! The following managed memory types:
+//! - boost::interprocess::segment_manager;
+//! - boost::interprocess::basic_managed_external_buffer
+//! - boost::interprocess::managed_external_buffer
+//! - boost::interprocess::wmanaged_external_buffer
+//! - boost::interprocess::basic_managed_shared_memory
+//! - boost::interprocess::managed_shared_memory
+//! - boost::interprocess::wmanaged_shared_memory
+//! - boost::interprocess::basic_managed_windows_shared_memory
+//! - boost::interprocess::managed_windows_shared_memory
+//! - boost::interprocess::wmanaged_windows_shared_memory
+//! - boost::interprocess::basic_managed_xsi_shared_memory
+//! - boost::interprocess::managed_xsi_shared_memory
+//! - boost::interprocess::wmanaged_xsi_shared_memory
+//! - boost::interprocess::fixed_managed_shared_memory
+//! - boost::interprocess::wfixed_managed_shared_memory
+//! - boost::interprocess::basic_managed_heap_memory
+//! - boost::interprocess::managed_heap_memory
+//! - boost::interprocess::wmanaged_heap_memory
+//! - boost::interprocess::basic_managed_mapped_file
+//! - boost::interprocess::managed_mapped_file
+//! - boost::interprocess::wmanaged_mapped_file
+//!
+//! The following exception types:
+//! - boost::interprocess::interprocess_exception
+//! - boost::interprocess::lock_exception
+//! - boost::interprocess::bad_alloc
+//!
+//! The following stream types:
+//! - boost::interprocess::basic_bufferbuf
+//! - boost::interprocess::basic_ibufferstream
+//! - boost::interprocess::basic_obufferstream
+//! - boost::interprocess::basic_bufferstream
+//! - boost::interprocess::basic_vectorbuf
+//! - boost::interprocess::basic_ivectorstream
+//! - boost::interprocess::basic_ovectorstream
+//! - boost::interprocess::basic_vectorstream
+//!
+//! The following smart pointer types:
+//! - boost::interprocess::scoped_ptr
+//! - boost::interprocess::intrusive_ptr
+//! - boost::interprocess::shared_ptr
+//! - boost::interprocess::weak_ptr
+//!
+//! The following interprocess communication types:
+//! - boost::interprocess::message_queue_t;
+//! - boost::interprocess::message_queue;
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
#include <cstddef>
//////////////////////////////////////////////////////////////////////////////
// Standard predeclarations
//////////////////////////////////////////////////////////////////////////////
-/// @cond
-
namespace boost{
namespace intrusive{
}}
@@ -41,8 +138,6 @@ namespace bi = boost::intrusive;
#include <iosfwd>
#include <string>
-/// @endcond
-
namespace boost { namespace interprocess {
//////////////////////////////////////////////////////////////////////////////
@@ -57,17 +152,20 @@ class permissions;
class shared_memory_object;
-#if defined (BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+#if defined (BOOST_INTERPROCESS_WINDOWS)
class windows_shared_memory;
#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
+#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS)
+class xsi_shared_memory;
+#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
+
//////////////////////////////////////////////////////////////////////////////
-// mapped file/mapped region/mapped_file
+// file mapping / mapped region
//////////////////////////////////////////////////////////////////////////////
class file_mapping;
class mapped_region;
-class mapped_file;
//////////////////////////////////////////////////////////////////////////////
// Mutexes
@@ -95,7 +193,6 @@ struct null_mutex_family;
// Other synchronization classes
//////////////////////////////////////////////////////////////////////////////
-class barrier;
class interprocess_sharable_mutex;
class interprocess_condition;
@@ -231,7 +328,7 @@ wmanaged_shared_memory;
// Windows shared memory managed memory classes
//////////////////////////////////////////////////////////////////////////////
-#if defined (BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+#if defined (BOOST_INTERPROCESS_WINDOWS)
template <class CharType
,class MemoryAlgorithm
@@ -252,7 +349,7 @@ wmanaged_windows_shared_memory;
#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
-#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS)
template <class CharType
,class MemoryAlgorithm
@@ -409,9 +506,7 @@ typedef message_queue_t<offset_ptr<void> > message_queue;
}} //namespace boost { namespace interprocess {
-//////////////////////////////////////////////////////////////////////////////
-// CONTAINERS
-//////////////////////////////////////////////////////////////////////////////
+#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#include <boost/interprocess/detail/config_end.hpp>
diff --git a/boost/interprocess/ipc/message_queue.hpp b/boost/interprocess/ipc/message_queue.hpp
index 67dd574f61..09290587d9 100644
--- a/boost/interprocess/ipc/message_queue.hpp
+++ b/boost/interprocess/ipc/message_queue.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP
#define BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -30,6 +34,7 @@
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/assert.hpp>
#include <algorithm> //std::lower_bound
#include <cstddef> //std::size_t
#include <cstring> //memcpy
@@ -42,17 +47,23 @@
namespace boost{ namespace interprocess{
+namespace ipcdetail
+{
+ template<class VoidPointer>
+ class msg_queue_initialization_func_t;
+}
+
//!A class that allows sending messages
//!between processes.
template<class VoidPointer>
class message_queue_t
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Blocking modes
enum block_t { blocking, timed, non_blocking };
message_queue_t();
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
typedef VoidPointer void_pointer;
@@ -99,7 +110,7 @@ class message_queue_t
//!Sends a message stored in buffer "buffer" with size "buffer_size" in the
//!message queue with priority "priority". If the message queue is full
- //!the sender is blocked. Throws interprocess_error on error.*/
+ //!the sender is blocked. Throws interprocess_error on error.
void send (const void *buffer, size_type buffer_size,
unsigned int priority);
@@ -155,15 +166,18 @@ class message_queue_t
//!Returns the number of messages currently stored.
//!Never throws
- size_type get_num_msg();
+ size_type get_num_msg() const;
//!Removes the message queue from the system.
//!Returns false on error. Never throws
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef boost::posix_time::ptime ptime;
+
+ friend class ipcdetail::msg_queue_initialization_func_t<VoidPointer>;
+
bool do_receive(block_t block,
void *buffer, size_type buffer_size,
size_type &recvd_size, unsigned int &priority,
@@ -176,12 +190,12 @@ class message_queue_t
//!Returns the needed memory size for the shared message queue.
//!Never throws
static size_type get_mem_size(size_type max_msg_size, size_type max_num_msg);
-
- ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem;
- /// @endcond
+ typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
+ open_create_impl_t m_shmem;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail {
@@ -227,9 +241,27 @@ class priority_functor
//!
//!-> offset_ptr<msg_hdr_t> index [max_num_msg]
//! An array of pointers with size "max_num_msg" called index. Each pointer
-//! points to a preallocated message. The elements of this array are
+//! points to a preallocated message. Elements of this array are
//! reordered in runtime in the following way:
//!
+//! IF BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is defined:
+//!
+//! When the current number of messages is "cur_num_msg", the array
+//! is treated like a circular buffer. Starting from position "cur_first_msg"
+//! "cur_num_msg" in a circular way, pointers point to inserted messages and the rest
+//! point to free messages. Those "cur_num_msg" pointers are
+//! ordered by the priority of the pointed message and by insertion order
+//! if two messages have the same priority. So the next message to be
+//! used in a "receive" is pointed by index [(cur_first_msg + cur_num_msg-1)%max_num_msg]
+//! and the first free message ready to be used in a "send" operation is
+//! [cur_first_msg] if circular buffer is extended from front,
+//! [(cur_first_msg + cur_num_msg)%max_num_msg] otherwise.
+//!
+//! This transforms the index in a circular buffer with an embedded free
+//! message queue.
+//!
+//! ELSE (BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is NOT defined):
+//!
//! When the current number of messages is "cur_num_msg", the first
//! "cur_num_msg" pointers point to inserted messages and the rest
//! point to free messages. The first "cur_num_msg" pointers are
@@ -237,11 +269,12 @@ class priority_functor
//! if two messages have the same priority. So the next message to be
//! used in a "receive" is pointed by index [cur_num_msg-1] and the first free
//! message ready to be used in a "send" operation is index [cur_num_msg].
-//! This transforms index in a fixed size priority queue with an embedded free
+//!
+//! This transforms the index in a fixed size priority queue with an embedded free
//! message queue.
//!
//!-> struct message_t
-//! {
+//! {
//! msg_hdr_t header;
//! char[max_msg_size] data;
//! } messages [max_num_msg];
@@ -252,7 +285,7 @@ class priority_functor
template<class VoidPointer>
class mq_hdr_t
: public ipcdetail::priority_functor<VoidPointer>
-{
+{
typedef VoidPointer void_pointer;
typedef msg_hdr_t<void_pointer> msg_header;
typedef typename boost::intrusive::
@@ -264,22 +297,24 @@ class mq_hdr_t
typedef typename boost::intrusive::
pointer_traits<void_pointer>::template
rebind_pointer<msg_hdr_ptr_t>::type msg_hdr_ptr_ptr_t;
+ typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
public:
//!Constructor. This object must be constructed in the beginning of the
//!shared memory of the size returned by the function "get_mem_size".
//!This constructor initializes the needed resources and creates
- //!the internal structures like the priority index. This can throw.*/
+ //!the internal structures like the priority index. This can throw.
mq_hdr_t(size_type max_num_msg, size_type max_msg_size)
: m_max_num_msg(max_num_msg),
m_max_msg_size(max_msg_size),
m_cur_num_msg(0)
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+ ,m_cur_first_msg(0u)
+ ,m_blocked_senders(0u)
+ ,m_blocked_receivers(0u)
+ #endif
{ this->initialize_memory(); }
- //!Returns the inserted message with top priority
- msg_header * top_msg()
- { return mp_index[m_cur_num_msg-1].get(); }
-
//!Returns true if the message queue is full
bool is_full() const
{ return m_cur_num_msg == m_max_num_msg; }
@@ -292,24 +327,195 @@ class mq_hdr_t
void free_top_msg()
{ --m_cur_num_msg; }
- //!Returns the first free msg of the free message queue
- msg_header * free_msg()
- { return mp_index[m_cur_num_msg].get(); }
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+
+ typedef msg_hdr_ptr_t *iterator;
+
+ size_type end_pos() const
+ {
+ const size_type space_until_bufend = m_max_num_msg - m_cur_first_msg;
+ return space_until_bufend > m_cur_num_msg
+ ? m_cur_first_msg + m_cur_num_msg : m_cur_num_msg - space_until_bufend;
+ }
+
+ //!Returns the inserted message with top priority
+ msg_header &top_msg()
+ {
+ size_type pos = this->end_pos();
+ return *mp_index[pos ? --pos : m_max_num_msg - 1];
+ }
+
+ //!Returns the inserted message with bottom priority
+ msg_header &bottom_msg()
+ { return *mp_index[m_cur_first_msg]; }
+
+ iterator inserted_ptr_begin() const
+ { return &mp_index[m_cur_first_msg]; }
+
+ iterator inserted_ptr_end() const
+ { return &mp_index[this->end_pos()]; }
+
+ iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor<VoidPointer> func)
+ {
+ iterator begin(this->inserted_ptr_begin()), end(this->inserted_ptr_end());
+ if(end < begin){
+ iterator idx_end = &mp_index[m_max_num_msg];
+ iterator ret = std::lower_bound(begin, idx_end, value, func);
+ if(idx_end == ret){
+ iterator idx_beg = &mp_index[0];
+ ret = std::lower_bound(idx_beg, end, value, func);
+ //sanity check, these cases should not call lower_bound (optimized out)
+ BOOST_ASSERT(ret != end);
+ BOOST_ASSERT(ret != begin);
+ return ret;
+ }
+ else{
+ return ret;
+ }
+ }
+ else{
+ return std::lower_bound(begin, end, value, func);
+ }
+ }
+
+ msg_header & insert_at(iterator where)
+ {
+ iterator it_inserted_ptr_end = this->inserted_ptr_end();
+ iterator it_inserted_ptr_beg = this->inserted_ptr_begin();
+ if(where == it_inserted_ptr_beg){
+ //unsigned integer guarantees underflow
+ m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg;
+ --m_cur_first_msg;
+ ++m_cur_num_msg;
+ return *mp_index[m_cur_first_msg];
+ }
+ else if(where == it_inserted_ptr_end){
+ ++m_cur_num_msg;
+ return **it_inserted_ptr_end;
+ }
+ else{
+ size_type pos = where - &mp_index[0];
+ size_type circ_pos = pos >= m_cur_first_msg ? pos - m_cur_first_msg : pos + (m_max_num_msg - m_cur_first_msg);
+ //Check if it's more efficient to move back or move front
+ if(circ_pos < m_cur_num_msg/2){
+ //The queue can't be full so m_cur_num_msg == 0 or m_cur_num_msg <= pos
+ //indicates two step insertion
+ if(!pos){
+ pos = m_max_num_msg;
+ where = &mp_index[m_max_num_msg-1];
+ }
+ else{
+ --where;
+ }
+ const bool unique_segment = m_cur_first_msg && m_cur_first_msg <= pos;
+ const size_type first_segment_beg = unique_segment ? m_cur_first_msg : 1u;
+ const size_type first_segment_end = pos;
+ const size_type second_segment_beg = unique_segment || !m_cur_first_msg ? m_max_num_msg : m_cur_first_msg;
+ const size_type second_segment_end = m_max_num_msg;
+ const msg_hdr_ptr_t backup = *(&mp_index[0] + (unique_segment ? first_segment_beg : second_segment_beg) - 1);
+
+ //First segment
+ if(!unique_segment){
+ std::copy( &mp_index[0] + second_segment_beg
+ , &mp_index[0] + second_segment_end
+ , &mp_index[0] + second_segment_beg - 1);
+ mp_index[m_max_num_msg-1] = mp_index[0];
+ }
+ std::copy( &mp_index[0] + first_segment_beg
+ , &mp_index[0] + first_segment_end
+ , &mp_index[0] + first_segment_beg - 1);
+ *where = backup;
+ m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg;
+ --m_cur_first_msg;
+ ++m_cur_num_msg;
+ return **where;
+ }
+ else{
+ //The queue can't be full so end_pos < m_cur_first_msg
+ //indicates two step insertion
+ const size_type pos_end = this->end_pos();
+ const bool unique_segment = pos < pos_end;
+ const size_type first_segment_beg = pos;
+ const size_type first_segment_end = unique_segment ? pos_end : m_max_num_msg-1;
+ const size_type second_segment_beg = 0u;
+ const size_type second_segment_end = unique_segment ? 0u : pos_end;
+ const msg_hdr_ptr_t backup = *it_inserted_ptr_end;
+
+ //First segment
+ if(!unique_segment){
+ std::copy_backward( &mp_index[0] + second_segment_beg
+ , &mp_index[0] + second_segment_end
+ , &mp_index[0] + second_segment_end + 1);
+ mp_index[0] = mp_index[m_max_num_msg-1];
+ }
+ std::copy_backward( &mp_index[0] + first_segment_beg
+ , &mp_index[0] + first_segment_end
+ , &mp_index[0] + first_segment_end + 1);
+ *where = backup;
+ ++m_cur_num_msg;
+ return **where;
+ }
+ }
+ }
+
+ #else //BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
+
+ typedef msg_hdr_ptr_t *iterator;
+
+ //!Returns the inserted message with top priority
+ msg_header &top_msg()
+ { return *mp_index[m_cur_num_msg-1]; }
+
+ //!Returns the inserted message with bottom priority
+ msg_header &bottom_msg()
+ { return *mp_index[0]; }
+
+ iterator inserted_ptr_begin() const
+ { return &mp_index[0]; }
+
+ iterator inserted_ptr_end() const
+ { return &mp_index[m_cur_num_msg]; }
+
+ iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor<VoidPointer> func)
+ { return std::lower_bound(this->inserted_ptr_begin(), this->inserted_ptr_end(), value, func); }
+
+ msg_header & insert_at(iterator pos)
+ {
+ const msg_hdr_ptr_t backup = *inserted_ptr_end();
+ std::copy_backward(pos, inserted_ptr_end(), inserted_ptr_end()+1);
+ *pos = backup;
+ ++m_cur_num_msg;
+ return **pos;
+ }
+
+ #endif //BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
//!Inserts the first free message in the priority queue
- void queue_free_msg()
- {
- //Get free msg
- msg_hdr_ptr_t free = mp_index[m_cur_num_msg];
+ msg_header & queue_free_msg(unsigned int priority)
+ {
//Get priority queue's range
- msg_hdr_ptr_t *it = &mp_index[0], *it_end = &mp_index[m_cur_num_msg];
- //Check where the free message should be placed
- it = std::lower_bound(it, it_end, free, static_cast<priority_functor<VoidPointer>&>(*this));
- //Make room in that position
- std::copy_backward(it, it_end, it_end+1);
+ iterator it (inserted_ptr_begin()), it_end(inserted_ptr_end());
+ //Optimize for non-priority usage
+ if(m_cur_num_msg && priority > this->bottom_msg().priority){
+ //Check for higher priority than all stored messages
+ if(priority > this->top_msg().priority){
+ it = it_end;
+ }
+ else{
+ //Since we don't now which free message we will pick
+ //build a dummy header for searches
+ msg_header dummy_hdr;
+ dummy_hdr.priority = priority;
+
+ //Get free msg
+ msg_hdr_ptr_t dummy_ptr(&dummy_hdr);
+
+ //Check where the free message should be placed
+ it = this->lower_bound(dummy_ptr, static_cast<priority_functor<VoidPointer>&>(*this));
+ }
+ }
//Insert the free message in the correct position
- *it = free;
- ++m_cur_num_msg;
+ return this->insert_at(it);
}
//!Returns the number of bytes needed to construct a message queue with
@@ -319,13 +525,13 @@ class mq_hdr_t
(size_type max_msg_size, size_type max_num_msg)
{
const size_type
- msg_hdr_align = ::boost::alignment_of<msg_header>::value,
- index_align = ::boost::alignment_of<msg_hdr_ptr_t>::value,
+ msg_hdr_align = ::boost::alignment_of<msg_header>::value,
+ index_align = ::boost::alignment_of<msg_hdr_ptr_t>::value,
r_hdr_size = ipcdetail::ct_rounded_size<sizeof(mq_hdr_t), index_align>::value,
- r_index_size = ipcdetail::get_rounded_size(sizeof(msg_hdr_ptr_t)*max_num_msg, msg_hdr_align),
- r_max_msg_size = ipcdetail::get_rounded_size(max_msg_size, msg_hdr_align) + sizeof(msg_header);
+ r_index_size = ipcdetail::get_rounded_size<size_type>(max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align),
+ r_max_msg_size = ipcdetail::get_rounded_size<size_type>(max_msg_size, msg_hdr_align) + sizeof(msg_header);
return r_hdr_size + r_index_size + (max_num_msg*r_max_msg_size) +
- ipcdetail::managed_open_or_create_impl<shared_memory_object>::ManagedOpenOrCreateUserOffset;
+ open_create_impl_t::ManagedOpenOrCreateUserOffset;
}
//!Initializes the memory structures to preallocate messages and constructs the
@@ -333,11 +539,11 @@ class mq_hdr_t
void initialize_memory()
{
const size_type
- msg_hdr_align = ::boost::alignment_of<msg_header>::value,
- index_align = ::boost::alignment_of<msg_hdr_ptr_t>::value,
+ msg_hdr_align = ::boost::alignment_of<msg_header>::value,
+ index_align = ::boost::alignment_of<msg_hdr_ptr_t>::value,
r_hdr_size = ipcdetail::ct_rounded_size<sizeof(mq_hdr_t), index_align>::value,
- r_index_size = ipcdetail::get_rounded_size(sizeof(msg_hdr_ptr_t)*m_max_num_msg, msg_hdr_align),
- r_max_msg_size = ipcdetail::get_rounded_size(m_max_msg_size, msg_hdr_align) + sizeof(msg_header);
+ r_index_size = ipcdetail::get_rounded_size<size_type>(m_max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align),
+ r_max_msg_size = ipcdetail::get_rounded_size<size_type>(m_max_msg_size, msg_hdr_align) + sizeof(msg_header);
//Pointer to the index
msg_hdr_ptr_t *index = reinterpret_cast<msg_hdr_ptr_t*>
@@ -345,7 +551,7 @@ class mq_hdr_t
//Pointer to the first message header
msg_header *msg_hdr = reinterpret_cast<msg_header*>
- (reinterpret_cast<char*>(this)+r_hdr_size+r_index_size);
+ (reinterpret_cast<char*>(this)+r_hdr_size+r_index_size);
//Initialize the pointer to the index
mp_index = index;
@@ -373,13 +579,19 @@ class mq_hdr_t
interprocess_condition m_cond_recv;
//Condition block senders when the queue is full
interprocess_condition m_cond_send;
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+ //Current start offset in the circular index
+ size_type m_cur_first_msg;
+ size_type m_blocked_senders;
+ size_type m_blocked_receivers;
+ #endif
};
//!This is the atomic functor to be executed when creating or opening
//!shared memory. Never throws
template<class VoidPointer>
-class initialization_func_t
+class msg_queue_initialization_func_t
{
public:
typedef typename boost::intrusive::
@@ -388,7 +600,7 @@ class initialization_func_t
typedef typename boost::intrusive::pointer_traits<char_ptr>::difference_type difference_type;
typedef typename boost::make_unsigned<difference_type>::type size_type;
- initialization_func_t(size_type maxmsg = 0,
+ msg_queue_initialization_func_t(size_type maxmsg = 0,
size_type maxmsgsize = 0)
: m_maxmsg (maxmsg), m_maxmsgsize(maxmsgsize) {}
@@ -403,12 +615,19 @@ class initialization_func_t
new (mptr) mq_hdr_t<VoidPointer>(m_maxmsg, m_maxmsgsize);
}
BOOST_CATCH(...){
- return false;
+ return false;
}
BOOST_CATCH_END
}
return true;
}
+
+ std::size_t get_min_size() const
+ {
+ return mq_hdr_t<VoidPointer>::get_mem_size(m_maxmsgsize, m_maxmsg)
+ - message_queue_t<VoidPointer>::open_create_impl_t::ManagedOpenOrCreateUserOffset;
+ }
+
const size_type m_maxmsg;
const size_type m_maxmsgsize;
};
@@ -425,7 +644,7 @@ inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPoin
{ return ipcdetail::mq_hdr_t<VoidPointer>::get_mem_size(max_msg_size, max_num_msg); }
template<class VoidPointer>
-inline message_queue_t<VoidPointer>::message_queue_t(create_only_t create_only,
+inline message_queue_t<VoidPointer>::message_queue_t(create_only_t,
const char *name,
size_type max_num_msg,
size_type max_msg_size,
@@ -433,16 +652,16 @@ inline message_queue_t<VoidPointer>::message_queue_t(create_only_t create_only,
//Create shared memory and execute functor atomically
: m_shmem(create_only,
name,
- get_mem_size(max_msg_size, max_num_msg),
+ get_mem_size(max_msg_size, max_num_msg),
read_write,
static_cast<void*>(0),
//Prepare initialization functor
- ipcdetail::initialization_func_t<VoidPointer> (max_num_msg, max_msg_size),
+ ipcdetail::msg_queue_initialization_func_t<VoidPointer> (max_num_msg, max_msg_size),
perm)
{}
template<class VoidPointer>
-inline message_queue_t<VoidPointer>::message_queue_t(open_or_create_t open_or_create,
+inline message_queue_t<VoidPointer>::message_queue_t(open_or_create_t,
const char *name,
size_type max_num_msg,
size_type max_msg_size,
@@ -454,20 +673,19 @@ inline message_queue_t<VoidPointer>::message_queue_t(open_or_create_t open_or_cr
read_write,
static_cast<void*>(0),
//Prepare initialization functor
- ipcdetail::initialization_func_t<VoidPointer> (max_num_msg, max_msg_size),
+ ipcdetail::msg_queue_initialization_func_t<VoidPointer> (max_num_msg, max_msg_size),
perm)
{}
template<class VoidPointer>
-inline message_queue_t<VoidPointer>::message_queue_t(open_only_t open_only,
- const char *name)
+inline message_queue_t<VoidPointer>::message_queue_t(open_only_t, const char *name)
//Create shared memory and execute functor atomically
: m_shmem(open_only,
name,
read_write,
static_cast<void*>(0),
//Prepare initialization functor
- ipcdetail::initialization_func_t<VoidPointer> ())
+ ipcdetail::msg_queue_initialization_func_t<VoidPointer> ())
{}
template<class VoidPointer>
@@ -503,63 +721,93 @@ inline bool message_queue_t<VoidPointer>::do_send(block_t block,
throw interprocess_exception(size_error);
}
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+ bool notify_blocked_receivers = false;
+ #endif
//---------------------------------------------
scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex);
//---------------------------------------------
{
//If the queue is full execute blocking logic
if (p_hdr->is_full()) {
-
- switch(block){
- case non_blocking :
- return false;
- break;
-
- case blocking :
- do{
- p_hdr->m_cond_send.wait(lock);
- }
- while (p_hdr->is_full());
- break;
-
- case timed :
- do{
- if(!p_hdr->m_cond_send.timed_wait(lock, abs_time)){
- if(p_hdr->is_full())
- return false;
- break;
+ BOOST_TRY{
+ #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
+ ++p_hdr->m_blocked_senders;
+ #endif
+ switch(block){
+ case non_blocking :
+ #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
+ --p_hdr->m_blocked_senders;
+ #endif
+ return false;
+ break;
+
+ case blocking :
+ do{
+ p_hdr->m_cond_send.wait(lock);
+ }
+ while (p_hdr->is_full());
+ break;
+
+ case timed :
+ do{
+ if(!p_hdr->m_cond_send.timed_wait(lock, abs_time)){
+ if(p_hdr->is_full()){
+ #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
+ --p_hdr->m_blocked_senders;
+ #endif
+ return false;
+ }
+ break;
+ }
}
- }
- while (p_hdr->is_full());
- break;
- default:
- break;
+ while (p_hdr->is_full());
+ break;
+ default:
+ break;
+ }
+ #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
+ --p_hdr->m_blocked_senders;
+ #endif
}
+ BOOST_CATCH(...){
+ #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
+ --p_hdr->m_blocked_senders;
+ #endif
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
}
-
- //Get the first free message from free message queue
- ipcdetail::msg_hdr_t<VoidPointer> *free_msg = p_hdr->free_msg();
- if (free_msg == 0) {
- throw interprocess_exception("boost::interprocess::message_queue corrupted");
- }
+
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+ notify_blocked_receivers = 0 != p_hdr->m_blocked_receivers;
+ #endif
+ //Insert the first free message in the priority queue
+ ipcdetail::msg_hdr_t<VoidPointer> &free_msg_hdr = p_hdr->queue_free_msg(priority);
+
+ //Sanity check, free msgs are always cleaned when received
+ BOOST_ASSERT(free_msg_hdr.priority == 0);
+ BOOST_ASSERT(free_msg_hdr.len == 0);
//Copy control data to the free message
- free_msg->priority = priority;
- free_msg->len = buffer_size;
+ free_msg_hdr.priority = priority;
+ free_msg_hdr.len = buffer_size;
//Copy user buffer to the message
- std::memcpy(free_msg->data(), buffer, buffer_size);
-
-// bool was_empty = p_hdr->is_empty();
- //Insert the first free message in the priority queue
- p_hdr->queue_free_msg();
-
- //If this message changes the queue empty state, notify it to receivers
-// if (was_empty){
- p_hdr->m_cond_recv.notify_one();
-// }
+ std::memcpy(free_msg_hdr.data(), buffer, buffer_size);
} // Lock end
+ //Notify outside lock to avoid contention. This might produce some
+ //spurious wakeups, but it's usually far better than notifying inside.
+ //If this message changes the queue empty state, notify it to receivers
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+ if (notify_blocked_receivers){
+ p_hdr->m_cond_recv.notify_one();
+ }
+ #else
+ p_hdr->m_cond_recv.notify_one();
+ #endif
+
return true;
}
@@ -600,86 +848,118 @@ inline bool
throw interprocess_exception(size_error);
}
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+ bool notify_blocked_senders = false;
+ #endif
//---------------------------------------------
scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex);
//---------------------------------------------
{
//If there are no messages execute blocking logic
if (p_hdr->is_empty()) {
- switch(block){
- case non_blocking :
- return false;
- break;
-
- case blocking :
- do{
- p_hdr->m_cond_recv.wait(lock);
- }
- while (p_hdr->is_empty());
- break;
-
- case timed :
- do{
- if(!p_hdr->m_cond_recv.timed_wait(lock, abs_time)){
- if(p_hdr->is_empty())
- return false;
- break;
+ BOOST_TRY{
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+ ++p_hdr->m_blocked_receivers;
+ #endif
+ switch(block){
+ case non_blocking :
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+ --p_hdr->m_blocked_receivers;
+ #endif
+ return false;
+ break;
+
+ case blocking :
+ do{
+ p_hdr->m_cond_recv.wait(lock);
}
- }
- while (p_hdr->is_empty());
- break;
-
- //Paranoia check
- default:
- break;
+ while (p_hdr->is_empty());
+ break;
+
+ case timed :
+ do{
+ if(!p_hdr->m_cond_recv.timed_wait(lock, abs_time)){
+ if(p_hdr->is_empty()){
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+ --p_hdr->m_blocked_receivers;
+ #endif
+ return false;
+ }
+ break;
+ }
+ }
+ while (p_hdr->is_empty());
+ break;
+
+ //Paranoia check
+ default:
+ break;
+ }
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+ --p_hdr->m_blocked_receivers;
+ #endif
+ }
+ BOOST_CATCH(...){
+ #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+ --p_hdr->m_blocked_receivers;
+ #endif
+ BOOST_RETHROW;
}
+ BOOST_CATCH_END
}
- //Thre is at least message ready to pick, get the top one
- ipcdetail::msg_hdr_t<VoidPointer> *top_msg = p_hdr->top_msg();
+ #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
+ notify_blocked_senders = 0 != p_hdr->m_blocked_senders;
+ #endif
- //Paranoia check
- if (top_msg == 0) {
- throw interprocess_exception("boost::interprocess::message_queue corrupted");
- }
+ //There is at least one message ready to pick, get the top one
+ ipcdetail::msg_hdr_t<VoidPointer> &top_msg = p_hdr->top_msg();
//Get data from the message
- recvd_size = top_msg->len;
- priority = top_msg->priority;
+ recvd_size = top_msg.len;
+ priority = top_msg.priority;
- //Copy data to receiver's bufers
- std::memcpy(buffer, top_msg->data(), recvd_size);
+ //Some cleanup to ease debugging
+ top_msg.len = 0;
+ top_msg.priority = 0;
-// bool was_full = p_hdr->is_full();
+ //Copy data to receiver's bufers
+ std::memcpy(buffer, top_msg.data(), recvd_size);
//Free top message and put it in the free message list
p_hdr->free_top_msg();
-
- //If this reception changes the queue full state, notify senders
-// if (was_full){
- p_hdr->m_cond_send.notify_one();
-// }
} //Lock end
+ //Notify outside lock to avoid contention. This might produce some
+ //spurious wakeups, but it's usually far better than notifying inside.
+ //If this reception changes the queue full state, notify senders
+ #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
+ if (notify_blocked_senders){
+ p_hdr->m_cond_send.notify_one();
+ }
+ #else
+ p_hdr->m_cond_send.notify_one();
+ #endif
+
return true;
}
template<class VoidPointer>
inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_max_msg() const
-{
+{
ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address());
return p_hdr ? p_hdr->m_max_num_msg : 0; }
template<class VoidPointer>
inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_max_msg_size() const
-{
+{
ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address());
- return p_hdr ? p_hdr->m_max_msg_size : 0;
+ return p_hdr ? p_hdr->m_max_msg_size : 0;
}
template<class VoidPointer>
-inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_num_msg()
-{
+inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_num_msg() const
+{
ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address());
if(p_hdr){
//---------------------------------------------
@@ -688,14 +968,20 @@ inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPoin
return p_hdr->m_cur_num_msg;
}
- return 0;
+ return 0;
}
template<class VoidPointer>
inline bool message_queue_t<VoidPointer>::remove(const char *name)
{ return shared_memory_object::remove(name); }
-/// @endcond
+#else
+
+//!Typedef for a default message queue
+//!to be used between processes
+typedef message_queue_t<offset_ptr<void> > message_queue;
+
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
}} //namespace boost{ namespace interprocess{
diff --git a/boost/interprocess/managed_external_buffer.hpp b/boost/interprocess/managed_external_buffer.hpp
index e268e57601..aa0c8c9d19 100644
--- a/boost/interprocess/managed_external_buffer.hpp
+++ b/boost/interprocess/managed_external_buffer.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP
#define BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -19,11 +19,11 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/detail/managed_memory_impl.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#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/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>
#include <boost/interprocess/indexes/iset_index.hpp>
@@ -45,12 +45,12 @@ template
class basic_managed_external_buffer
: public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType>
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType> base_t;
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_external_buffer)
- /// @endcond
-
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
public:
typedef typename base_t::size_type size_type;
@@ -104,6 +104,26 @@ class basic_managed_external_buffer
{ base_t::swap(other); }
};
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Typedef for a default basic_managed_external_buffer
+//!of narrow characters
+typedef basic_managed_external_buffer
+ <char
+ ,rbtree_best_fit<null_mutex_family>
+ ,iset_index>
+managed_external_buffer;
+
+//!Typedef for a default basic_managed_external_buffer
+//!of wide characters
+typedef basic_managed_external_buffer
+ <wchar_t
+ ,rbtree_best_fit<null_mutex_family>
+ ,iset_index>
+wmanaged_external_buffer;
+
+#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/managed_heap_memory.hpp b/boost/interprocess/managed_heap_memory.hpp
index 87107855f2..77ba56d75a 100644
--- a/boost/interprocess/managed_heap_memory.hpp
+++ b/boost/interprocess/managed_heap_memory.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,20 +11,20 @@
#ifndef BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP
#define BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
#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/move/utility_core.hpp>
#include <vector>
#include <boost/interprocess/detail/managed_memory_impl.hpp>
#include <boost/detail/no_exceptions_support.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/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>
#include <boost/interprocess/indexes/iset_index.hpp>
@@ -46,13 +46,13 @@ template
class basic_managed_heap_memory
: public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType>
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType> base_t;
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_heap_memory)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public: //functions
typedef typename base_t::size_type size_type;
@@ -99,7 +99,7 @@ class basic_managed_heap_memory
//!have some extra bytes to allocate new objects. If returns
//!false, the heap allocation has failed.
bool grow(size_type extra_bytes)
- {
+ {
//If memory is reallocated, data will
//be automatically copied
BOOST_TRY{
@@ -125,19 +125,38 @@ class basic_managed_heap_memory
m_heapmem.swap(other.m_heapmem);
}
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
//!Frees resources. Never throws.
void priv_close()
- {
+ {
base_t::destroy_impl();
std::vector<char>().swap(m_heapmem);
}
std::vector<char> m_heapmem;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Typedef for a default basic_managed_heap_memory
+//!of narrow characters
+typedef basic_managed_heap_memory
+ <char
+ ,rbtree_best_fit<null_mutex_family>
+ ,iset_index>
+managed_heap_memory;
+
+//!Typedef for a default basic_managed_heap_memory
+//!of wide characters
+typedef basic_managed_heap_memory
+ <wchar_t
+ ,rbtree_best_fit<null_mutex_family>
+ ,iset_index>
+wmanaged_heap_memory;
+
+#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/managed_mapped_file.hpp b/boost/interprocess/managed_mapped_file.hpp
index 5a351adfa5..ee74c9f165 100644
--- a/boost/interprocess/managed_mapped_file.hpp
+++ b/boost/interprocess/managed_mapped_file.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP
#define BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -21,17 +21,27 @@
#include <boost/interprocess/detail/managed_memory_impl.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/detail/file_wrapper.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/permissions.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/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>
#include <boost/interprocess/indexes/iset_index.hpp>
namespace boost {
namespace interprocess {
+namespace ipcdetail {
+
+template<class AllocationAlgorithm>
+struct mfile_open_or_create
+{
+ typedef ipcdetail::managed_open_or_create_impl
+ < file_wrapper, AllocationAlgorithm::Alignment, true, false> type;
+};
+
+} //namespace ipcdetail {
//!A basic mapped file named object creation class. Initializes the
//!mapped file. Inherits all basic functionality from
@@ -43,27 +53,22 @@ template
template<class IndexConfig> class IndexType
>
class basic_managed_mapped_file
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
: public ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType
- ,ipcdetail::managed_open_or_create_impl< ipcdetail::file_wrapper
- , AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset
- >
+ ,ipcdetail::mfile_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset>
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
public:
typedef ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType,
- ipcdetail::managed_open_or_create_impl
- <ipcdetail::file_wrapper, AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset
- > base_t;
+ ipcdetail::mfile_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> base_t;
typedef ipcdetail::file_wrapper device_type;
- typedef typename base_t::size_type size_type;
private:
- typedef ipcdetail::create_open_func<base_t> create_open_func_t;
- typedef ipcdetail::managed_open_or_create_impl< ipcdetail::file_wrapper
- , AllocationAlgorithm::Alignment> managed_open_or_create_type;
+ typedef ipcdetail::create_open_func<base_t> create_open_func_t;
basic_managed_mapped_file *get_this_pointer()
{ return this; }
@@ -71,10 +76,14 @@ class basic_managed_mapped_file
private:
typedef typename base_t::char_ptr_holder_t char_ptr_holder_t;
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_mapped_file)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public: //functions
+ //!Unsigned integral type enough to represent
+ //!the size of a basic_managed_mapped_file.
+ typedef typename BOOST_INTERPROCESS_IMPDEF(base_t::size_type) size_type;
+
//!Creates mapped file and creates and places the segment manager.
//!This can throw.
basic_managed_mapped_file()
@@ -82,7 +91,7 @@ class basic_managed_mapped_file
//!Creates mapped file and creates and places the segment manager.
//!This can throw.
- basic_managed_mapped_file(create_only_t create_only, const char *name,
+ basic_managed_mapped_file(create_only_t, const char *name,
size_type size, const void *addr = 0, const permissions &perm = permissions())
: m_mfile(create_only, name, size, read_write, addr,
create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm)
@@ -92,7 +101,7 @@ class basic_managed_mapped_file
//!segment was not created. If segment was created it connects to the
//!segment.
//!This can throw.
- basic_managed_mapped_file (open_or_create_t open_or_create,
+ basic_managed_mapped_file (open_or_create_t,
const char *name, size_type size,
const void *addr = 0, const permissions &perm = permissions())
: m_mfile(open_or_create, name, size, read_write, addr,
@@ -102,7 +111,7 @@ class basic_managed_mapped_file
//!Connects to a created mapped file and its segment manager.
//!This can throw.
- basic_managed_mapped_file (open_only_t open_only, const char* name,
+ basic_managed_mapped_file (open_only_t, const char* name,
const void *addr = 0)
: m_mfile(open_only, name, read_write, addr,
create_open_func_t(get_this_pointer(),
@@ -188,7 +197,7 @@ class basic_managed_mapped_file
<basic_managed_mapped_file>(filename);
}
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Tries to find a previous named allocation address. Returns a memory
//!buffer and the object count. If not found returned pointer is 0.
@@ -205,10 +214,30 @@ class basic_managed_mapped_file
}
private:
- managed_open_or_create_type m_mfile;
- /// @endcond
+ typename ipcdetail::mfile_open_or_create<AllocationAlgorithm>::type m_mfile;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Typedef for a default basic_managed_mapped_file
+//!of narrow characters
+typedef basic_managed_mapped_file
+ <char
+ ,rbtree_best_fit<mutex_family>
+ ,iset_index>
+managed_mapped_file;
+
+//!Typedef for a default basic_managed_mapped_file
+//!of wide characters
+typedef basic_managed_mapped_file
+ <wchar_t
+ ,rbtree_best_fit<mutex_family>
+ ,iset_index>
+wmanaged_mapped_file;
+
+#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/managed_shared_memory.hpp b/boost/interprocess/managed_shared_memory.hpp
index 0f74c1a0b9..b58ca51dfc 100644
--- a/boost/interprocess/managed_shared_memory.hpp
+++ b/boost/interprocess/managed_shared_memory.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP
#define BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -25,13 +25,23 @@
#include <boost/interprocess/permissions.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/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>
namespace boost {
-
namespace interprocess {
+namespace ipcdetail {
+
+template<class AllocationAlgorithm>
+struct shmem_open_or_create
+{
+ typedef ipcdetail::managed_open_or_create_impl
+ < shared_memory_object, AllocationAlgorithm::Alignment, true, false> type;
+};
+
+} //namespace ipcdetail {
+
//!A basic shared memory named object creation class. Initializes the
//!shared memory segment. Inherits all basic functionality from
//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/
@@ -44,18 +54,14 @@ template
class basic_managed_shared_memory
: public ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType
- ,ipcdetail::managed_open_or_create_impl<shared_memory_object
- , AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset>
- , private ipcdetail::managed_open_or_create_impl<shared_memory_object
- , AllocationAlgorithm::Alignment>
+ ,ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset>
+ , private ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType,
- ipcdetail::managed_open_or_create_impl
- < shared_memory_object, AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset> base_t;
- typedef ipcdetail::managed_open_or_create_impl
- <shared_memory_object, AllocationAlgorithm::Alignment> base2_t;
+ ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> base_t;
+ typedef typename ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type base2_t;
typedef ipcdetail::create_open_func<base_t> create_open_func_t;
@@ -69,7 +75,7 @@ class basic_managed_shared_memory
private:
typedef typename base_t::char_ptr_holder_t char_ptr_holder_t;
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_shared_memory)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public: //functions
@@ -89,7 +95,7 @@ class basic_managed_shared_memory
//!Creates shared memory and creates and places the segment manager.
//!This can throw.
- basic_managed_shared_memory(create_only_t create_only, const char *name,
+ basic_managed_shared_memory(create_only_t, const char *name,
size_type size, const void *addr = 0, const permissions& perm = permissions())
: base_t()
, base2_t(create_only, name, size, read_write, addr,
@@ -100,7 +106,7 @@ class basic_managed_shared_memory
//!segment was not created. If segment was created it connects to the
//!segment.
//!This can throw.
- basic_managed_shared_memory (open_or_create_t open_or_create,
+ basic_managed_shared_memory (open_or_create_t,
const char *name, size_type size,
const void *addr = 0, const permissions& perm = permissions())
: base_t()
@@ -133,7 +139,7 @@ class basic_managed_shared_memory
//!Connects to a created shared memory and its segment manager.
//!This can throw.
- basic_managed_shared_memory (open_only_t open_only, const char* name,
+ basic_managed_shared_memory (open_only_t, const char* name,
const void *addr = 0)
: base_t()
, base2_t(open_only, name, read_write, addr,
@@ -187,7 +193,7 @@ class basic_managed_shared_memory
return base_t::template shrink_to_fit
<basic_managed_shared_memory>(shmname);
}
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Tries to find a previous named allocation address. Returns a memory
//!buffer and the object count. If not found returned pointer is 0.
@@ -203,9 +209,46 @@ class basic_managed_shared_memory
}
}
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Typedef for a default basic_managed_shared_memory
+//!of narrow characters
+typedef basic_managed_shared_memory
+ <char
+ ,rbtree_best_fit<mutex_family>
+ ,iset_index>
+managed_shared_memory;
+
+//!Typedef for a default basic_managed_shared_memory
+//!of wide characters
+typedef basic_managed_shared_memory
+ <wchar_t
+ ,rbtree_best_fit<mutex_family>
+ ,iset_index>
+wmanaged_shared_memory;
+
+//!Typedef for a default basic_managed_shared_memory
+//!of narrow characters to be placed in a fixed address
+typedef basic_managed_shared_memory
+ <char
+ ,rbtree_best_fit<mutex_family, void*>
+ ,iset_index>
+fixed_managed_shared_memory;
+
+//!Typedef for a default basic_managed_shared_memory
+//!of narrow characters to be placed in a fixed address
+typedef basic_managed_shared_memory
+ <wchar_t
+ ,rbtree_best_fit<mutex_family, void*>
+ ,iset_index>
+wfixed_managed_shared_memory;
+
+
+#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/managed_windows_shared_memory.hpp b/boost/interprocess/managed_windows_shared_memory.hpp
index 414007a614..2298c799ba 100644
--- a/boost/interprocess/managed_windows_shared_memory.hpp
+++ b/boost/interprocess/managed_windows_shared_memory.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP
#define BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -22,16 +22,27 @@
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/windows_shared_memory.hpp>
#include <boost/interprocess/permissions.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.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/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>
#include <boost/interprocess/indexes/iset_index.hpp>
namespace boost {
namespace interprocess {
+namespace ipcdetail {
+
+template<class AllocationAlgorithm>
+struct wshmem_open_or_create
+{
+ typedef ipcdetail::managed_open_or_create_impl
+ < windows_shared_memory, AllocationAlgorithm::Alignment, false, false> type;
+};
+
+} //namespace ipcdetail {
+
//!A basic managed windows shared memory creation class. Initializes the
//!shared memory segment. Inherits all basic functionality from
//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>
@@ -52,18 +63,13 @@ template
class basic_managed_windows_shared_memory
: public ipcdetail::basic_managed_memory_impl
< CharType, AllocationAlgorithm, IndexType
- , ipcdetail::managed_open_or_create_impl
- < windows_shared_memory
- , AllocationAlgorithm::Alignment
- , false>::ManagedOpenOrCreateUserOffset
- >
+ , ipcdetail::wshmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset>
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType,
- ipcdetail::managed_open_or_create_impl
- <windows_shared_memory, AllocationAlgorithm::Alignment, false>::ManagedOpenOrCreateUserOffset> base_t;
+ ipcdetail::wshmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> base_t;
typedef ipcdetail::create_open_func<base_t> create_open_func_t;
basic_managed_windows_shared_memory *get_this_pointer()
@@ -72,7 +78,7 @@ class basic_managed_windows_shared_memory
private:
typedef typename base_t::char_ptr_holder_t char_ptr_holder_t;
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_windows_shared_memory)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public: //functions
typedef typename base_t::size_type size_type;
@@ -85,7 +91,7 @@ class basic_managed_windows_shared_memory
//!Creates shared memory and creates and places the segment manager.
//!This can throw.
basic_managed_windows_shared_memory
- (create_only_t create_only, const char *name,
+ (create_only_t, const char *name,
size_type size, const void *addr = 0, const permissions &perm = permissions())
: m_wshm(create_only, name, size, read_write, addr,
create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm)
@@ -96,7 +102,7 @@ class basic_managed_windows_shared_memory
//!segment.
//!This can throw.
basic_managed_windows_shared_memory
- (open_or_create_t open_or_create,
+ (open_or_create_t,
const char *name, size_type size,
const void *addr = 0,
const permissions &perm = permissions())
@@ -108,7 +114,7 @@ class basic_managed_windows_shared_memory
//!Connects to a created shared memory and its segment manager.
//!This can throw.
basic_managed_windows_shared_memory
- (open_only_t open_only, const char* name, const void *addr = 0)
+ (open_only_t, const char* name, const void *addr = 0)
: m_wshm(open_only, name, read_write, addr,
create_open_func_t(get_this_pointer(),
ipcdetail::DoOpen))
@@ -164,7 +170,7 @@ class basic_managed_windows_shared_memory
m_wshm.swap(other.m_wshm);
}
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Tries to find a previous named allocation address. Returns a memory
//!buffer and the object count. If not found returned pointer is 0.
@@ -181,11 +187,31 @@ class basic_managed_windows_shared_memory
}
private:
- ipcdetail::managed_open_or_create_impl< windows_shared_memory
- , AllocationAlgorithm::Alignment, false> m_wshm;
- /// @endcond
+ typename ipcdetail::wshmem_open_or_create<AllocationAlgorithm>::type m_wshm;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Typedef for a default basic_managed_windows_shared_memory
+//!of narrow characters
+typedef basic_managed_windows_shared_memory
+ <char
+ ,rbtree_best_fit<mutex_family>
+ ,iset_index>
+managed_windows_shared_memory;
+
+//!Typedef for a default basic_managed_windows_shared_memory
+//!of wide characters
+typedef basic_managed_windows_shared_memory
+ <wchar_t
+ ,rbtree_best_fit<mutex_family>
+ ,iset_index>
+wmanaged_windows_shared_memory;
+
+#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/managed_xsi_shared_memory.hpp b/boost/interprocess/managed_xsi_shared_memory.hpp
index dc909f6824..f7a4b35c35 100644
--- a/boost/interprocess/managed_xsi_shared_memory.hpp
+++ b/boost/interprocess/managed_xsi_shared_memory.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP
#define BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -28,7 +28,7 @@
#include <boost/interprocess/creation_tags.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/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>
#include <boost/interprocess/indexes/iset_index.hpp>
@@ -36,9 +36,20 @@ namespace boost {
namespace interprocess {
+namespace ipcdetail {
+
+template<class AllocationAlgorithm>
+struct xsishmem_open_or_create
+{
+ typedef ipcdetail::managed_open_or_create_impl //!FileBased, StoreDevice
+ < xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment, false, true> type;
+};
+
+} //namespace ipcdetail {
+
//!A basic X/Open System Interface (XSI) shared memory named object creation class. Initializes the
//!shared memory segment. Inherits all basic functionality from
-//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/
+//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>
template
<
class CharType,
@@ -48,19 +59,15 @@ template
class basic_managed_xsi_shared_memory
: public ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType
- ,ipcdetail::managed_open_or_create_impl
- < xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment
- , false, true>::ManagedOpenOrCreateUserOffset>
- , private ipcdetail::managed_open_or_create_impl
- <xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment, false, true>
+ ,ipcdetail::xsishmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset>
+ , private ipcdetail::xsishmem_open_or_create<AllocationAlgorithm>::type
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
public:
typedef xsi_shared_memory_file_wrapper device_type;
public:
- typedef ipcdetail::managed_open_or_create_impl
- <xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment, false, true> base2_t;
+ typedef typename ipcdetail::xsishmem_open_or_create<AllocationAlgorithm>::type base2_t;
typedef ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType,
base2_t::ManagedOpenOrCreateUserOffset> base_t;
@@ -73,7 +80,7 @@ class basic_managed_xsi_shared_memory
private:
typedef typename base_t::char_ptr_holder_t char_ptr_holder_t;
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_xsi_shared_memory)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public: //functions
typedef typename base_t::size_type size_type;
@@ -94,7 +101,7 @@ class basic_managed_xsi_shared_memory
//!Creates shared memory and creates and places the segment manager.
//!This can throw.
- basic_managed_xsi_shared_memory(create_only_t create_only, const xsi_key &key,
+ basic_managed_xsi_shared_memory(create_only_t, const xsi_key &key,
std::size_t size, const void *addr = 0, const permissions& perm = permissions())
: base_t()
, base2_t(create_only, key, size, read_write, addr,
@@ -105,7 +112,7 @@ class basic_managed_xsi_shared_memory
//!segment was not created. If segment was created it connects to the
//!segment.
//!This can throw.
- basic_managed_xsi_shared_memory (open_or_create_t open_or_create,
+ basic_managed_xsi_shared_memory (open_or_create_t,
const xsi_key &key, std::size_t size,
const void *addr = 0, const permissions& perm = permissions())
: base_t()
@@ -127,7 +134,7 @@ class basic_managed_xsi_shared_memory
//!Connects to a created shared memory and its segment manager.
//!This can throw.
- basic_managed_xsi_shared_memory (open_only_t open_only, const xsi_key &key,
+ basic_managed_xsi_shared_memory (open_only_t, const xsi_key &key,
const void *addr = 0)
: base_t()
, base2_t(open_only, key, read_write, addr,
@@ -170,7 +177,7 @@ class basic_managed_xsi_shared_memory
int get_shmid() const
{ return base2_t::get_device().get_shmid(); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Tries to find a previous named allocation address. Returns a memory
//!buffer and the object count. If not found returned pointer is 0.
@@ -186,9 +193,29 @@ class basic_managed_xsi_shared_memory
}
}
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Typedef for a default basic_managed_xsi_shared_memory
+//!of narrow characters
+typedef basic_managed_xsi_shared_memory
+ <char
+ ,rbtree_best_fit<mutex_family>
+ ,iset_index>
+managed_xsi_shared_memory;
+
+//!Typedef for a default basic_managed_xsi_shared_memory
+//!of wide characters
+typedef basic_managed_xsi_shared_memory
+ <wchar_t
+ ,rbtree_best_fit<mutex_family>
+ ,iset_index>
+wmanaged_xsi_shared_memory;
+
+#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/mapped_region.hpp b/boost/interprocess/mapped_region.hpp
index 522c1e403a..24e55263ea 100644
--- a/boost/interprocess/mapped_region.hpp
+++ b/boost/interprocess/mapped_region.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,16 +11,33 @@
#ifndef BOOST_INTERPROCESS_MAPPED_REGION_HPP
#define BOOST_INTERPROCESS_MAPPED_REGION_HPP
+#if defined(_MSC_VER)
+# 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/exceptions.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <string>
#include <boost/cstdint.hpp>
+#include <boost/assert.hpp>
+//Some Unixes use caddr_t instead of void * in madvise
+// SunOS Tru64 HP-UX AIX
+#if defined(sun) || defined(__sun) || defined(__osf__) || defined(__osf) || defined(_hpux) || defined(hpux) || defined(_AIX)
+#define BOOST_INTERPROCESS_MADVISE_USES_CADDR_T
+#include <sys/types.h>
+#endif
+
+//A lot of UNIXes have destructive semantics for MADV_DONTNEED, so
+//we need to be careful to allow it.
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+#define BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS
+#endif
#if defined (BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
@@ -40,7 +57,7 @@
# error Unknown platform
# endif
-#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
+#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
//!\file
//!Describes mapped region class
@@ -48,11 +65,18 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+//Solaris declares madvise only in some configurations but defines MADV_XXX, a bit confusing.
+//Predeclare it here to avoid any compilation error
+#if (defined(sun) || defined(__sun)) && defined(MADV_NORMAL)
+extern "C" int madvise(caddr_t, size_t, int);
+#endif
+
namespace ipcdetail{ class interprocess_tester; }
namespace ipcdetail{ class raw_mapped_region_creator; }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!The mapped_region class represents a portion or region created from a
//!memory_mappable object.
@@ -62,10 +86,10 @@ namespace ipcdetail{ class raw_mapped_region_creator; }
//!the region specified by the user.
class mapped_region
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
BOOST_MOVABLE_BUT_NOT_COPYABLE(mapped_region)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
@@ -76,6 +100,22 @@ class mapped_region
//!If an address is specified, both the offset and the address must be
//!multiples of the page size.
//!
+ //!The map is created using "default_map_options". This flag is OS
+ //!dependant and it should not be changed unless the user needs to
+ //!specify special options.
+ //!
+ //!In Windows systems "map_options" is a DWORD value passed as
+ //!"dwDesiredAccess" to "MapViewOfFileEx". If "default_map_options" is passed
+ //!it's initialized to zero. "map_options" is XORed with FILE_MAP_[COPY|READ|WRITE].
+ //!
+ //!In UNIX systems and POSIX mappings "map_options" is an int value passed as "flags"
+ //!to "mmap". If "default_map_options" is specified it's initialized to MAP_NOSYNC
+ //!if that option exists and to zero otherwise. "map_options" XORed with MAP_PRIVATE or MAP_SHARED.
+ //!
+ //!In UNIX systems and XSI mappings "map_options" is an int value passed as "shmflg"
+ //!to "shmat". If "default_map_options" is specified it's initialized to zero.
+ //!"map_options" is XORed with SHM_RDONLY if needed.
+ //!
//!The OS could allocate more pages than size/page_size(), but get_address()
//!will always return the address passed in this function (if not null) and
//!get_size() will return the specified size.
@@ -84,7 +124,8 @@ class mapped_region
,mode_t mode
,offset_t offset = 0
,std::size_t size = 0
- ,const void *address = 0);
+ ,const void *address = 0
+ ,map_options_t map_options = default_map_options);
//!Default constructor. Address will be 0 (nullptr).
//!Size will be 0.
@@ -117,6 +158,10 @@ class mapped_region
return *this;
}
+ //!Swaps the mapped_region with another
+ //!mapped region
+ void swap(mapped_region &other);
+
//!Returns the size of the mapping. Never throws.
std::size_t get_size() const;
@@ -135,16 +180,48 @@ class mapped_region
//!Never throws. Returns false if operation could not be performed.
bool flush(std::size_t mapping_offset = 0, std::size_t numbytes = 0, bool async = true);
- //!Swaps the mapped_region with another
- //!mapped region
- void swap(mapped_region &other);
+ //!Shrinks current mapped region. If after shrinking there is no longer need for a previously
+ //!mapped memory page, accessing that page can trigger a segmentation fault.
+ //!Depending on the OS, this operation might fail (XSI shared memory), it can decommit storage
+ //!and free a portion of the virtual address space (e.g.POSIX) or this
+ //!function can release some physical memory wihout freeing any virtual address space(Windows).
+ //!Returns true on success. Never throws.
+ bool shrink_by(std::size_t bytes, bool from_back = true);
+
+ //!This enum specifies region usage behaviors that an application can specify
+ //!to the mapped region implementation.
+ enum advice_types{
+ //!Specifies that the application has no advice to give on its behavior with respect to
+ //!the region. It is the default characteristic if no advice is given for a range of memory.
+ advice_normal,
+ //!Specifies that the application expects to access the region sequentially from
+ //!lower addresses to higher addresses. The implementation can lower the priority of
+ //!preceding pages within the region once a page have been accessed.
+ advice_sequential,
+ //!Specifies that the application expects to access the region in a random order,
+ //!and prefetching is likely not advantageous.
+ advice_random,
+ //!Specifies that the application expects to access the region in the near future.
+ //!The implementation can prefetch pages of the region.
+ advice_willneed,
+ //!Specifies that the application expects that it will not access the region in the near future.
+ //!The implementation can unload pages within the range to save system resources.
+ advice_dontneed
+ };
+
+ //!Advises the implementation on the expected behavior of the application with respect to the data
+ //!in the region. The implementation may use this information to optimize handling of the region data.
+ //!This function has no effect on the semantics of access to memory in the region, although it may affect
+ //!the performance of access.
+ //!If the advise type is not known to the implementation, the function returns false. True otherwise.
+ bool advise(advice_types advise);
//!Returns the size of the page. This size is the minimum memory that
//!will be used by the system when mapping a memory mappable source and
//!will restrict the address and the offset to map.
static std::size_t get_page_size();
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
//!Closes a previously opened memory mapping. Never throws
void priv_close();
@@ -152,6 +229,7 @@ class mapped_region
void* priv_map_address() const;
std::size_t priv_map_size() const;
bool priv_flush_param_check(std::size_t mapping_offset, void *&addr, std::size_t &numbytes) const;
+ bool priv_shrink_param_check(std::size_t bytes, bool from_back, void *&shrink_page_start, std::size_t &shrink_page_bytes);
static void priv_size_from_mapping_size
(offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size);
static offset_t priv_page_offset_addr_fixup(offset_t page_offset, const void *&addr);
@@ -180,10 +258,10 @@ class mapped_region
template<int Dummy>
static void destroy_syncs_in_range(const void *addr, std::size_t size);
#endif
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-///@cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void swap(mapped_region &x, mapped_region &y)
{ x.swap(y); }
@@ -226,6 +304,38 @@ inline bool mapped_region::priv_flush_param_check
return true;
}
+inline bool mapped_region::priv_shrink_param_check
+ (std::size_t bytes, bool from_back, void *&shrink_page_start, std::size_t &shrink_page_bytes)
+{
+ //Check some errors
+ if(m_base == 0 || bytes > m_size){
+ return false;
+ }
+ else if(bytes == m_size){
+ this->priv_close();
+ return true;
+ }
+ else{
+ const std::size_t page_size = mapped_region::get_page_size();
+ if(from_back){
+ const std::size_t new_pages = (m_size + m_page_offset - bytes - 1)/page_size + 1;
+ shrink_page_start = static_cast<char*>(this->priv_map_address()) + new_pages*page_size;
+ shrink_page_bytes = m_page_offset + m_size - new_pages*page_size;
+ m_size -= bytes;
+ }
+ else{
+ shrink_page_start = this->priv_map_address();
+ m_page_offset += bytes;
+ shrink_page_bytes = (m_page_offset/page_size)*page_size;
+ m_page_offset = m_page_offset % page_size;
+ m_size -= bytes;
+ m_base = static_cast<char *>(m_base) + bytes;
+ BOOST_ASSERT(shrink_page_bytes%page_size == 0);
+ }
+ return true;
+ }
+}
+
inline void mapped_region::priv_size_from_mapping_size
(offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size)
{
@@ -268,7 +378,7 @@ template<int dummy>
inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size()
{
winapi::system_info info;
- get_system_info(&info);
+ winapi::get_system_info(&info);
return std::size_t(info.dwAllocationGranularity);
}
@@ -278,7 +388,8 @@ inline mapped_region::mapped_region
,mode_t mode
,offset_t offset
,std::size_t size
- ,const void *address)
+ ,const void *address
+ ,map_options_t map_options)
: m_base(0), m_size(0), m_page_offset(0), m_mode(mode)
, m_file_or_mapping_hnd(ipcdetail::invalid_file())
{
@@ -290,7 +401,7 @@ inline mapped_region::mapped_region
//For "create_file_mapping"
unsigned long protection = 0;
//For "mapviewoffile"
- unsigned long map_access = 0;
+ unsigned long map_access = map_options == default_map_options ? 0 : map_options;
switch(mode)
{
@@ -356,7 +467,6 @@ inline mapped_region::mapped_region
priv_size_from_mapping_size(mapping_size, offset, page_offset, size);
}
-
//Map with new offsets and size
void *base = winapi::map_view_of_file_ex
(native_mapping_handle,
@@ -398,13 +508,44 @@ inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbyte
}
//m_file_or_mapping_hnd can be a file handle or a mapping handle.
//so flushing file buffers has only sense for files...
- else if(async && m_file_or_mapping_hnd != winapi::invalid_handle_value &&
+ else if(!async && m_file_or_mapping_hnd != winapi::invalid_handle_value &&
winapi::get_file_type(m_file_or_mapping_hnd) == winapi::file_type_disk){
return winapi::flush_file_buffers(m_file_or_mapping_hnd);
}
return true;
}
+inline bool mapped_region::shrink_by(std::size_t bytes, bool from_back)
+{
+ void *shrink_page_start;
+ std::size_t shrink_page_bytes;
+ if(!this->priv_shrink_param_check(bytes, from_back, shrink_page_start, shrink_page_bytes)){
+ return false;
+ }
+ else if(shrink_page_bytes){
+ //In Windows, we can't decommit the storage or release the virtual address space,
+ //the best we can do is try to remove some memory from the process working set.
+ //With a bit of luck we can free some physical memory.
+ unsigned long old_protect_ignored;
+ bool b_ret = winapi::virtual_unlock(shrink_page_start, shrink_page_bytes)
+ || (winapi::get_last_error() == winapi::error_not_locked);
+ (void)old_protect_ignored;
+ //Change page protection to forbid any further access
+ b_ret = b_ret && winapi::virtual_protect
+ (shrink_page_start, shrink_page_bytes, winapi::page_noaccess, old_protect_ignored);
+ return b_ret;
+ }
+ else{
+ return true;
+ }
+}
+
+inline bool mapped_region::advise(advice_types)
+{
+ //Windows has no madvise/posix_madvise equivalent
+ return false;
+}
+
inline void mapped_region::priv_close()
{
if(m_base){
@@ -424,7 +565,7 @@ inline void mapped_region::priv_close()
inline void mapped_region::dont_close_on_destruction()
{}
-#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
+#else //#if defined (BOOST_INTERPROCESS_WINDOWS)
inline mapped_region::mapped_region()
: m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false)
@@ -440,7 +581,8 @@ inline mapped_region::mapped_region
, mode_t mode
, offset_t offset
, std::size_t size
- , const void *address)
+ , const void *address
+ , map_options_t map_options)
: m_base(0), m_size(0), m_page_offset(0), m_mode(mode), m_is_xsi(false)
{
mapping_handle_t map_hnd = mapping.get_mapping_handle();
@@ -464,7 +606,7 @@ inline mapped_region::mapped_region
throw interprocess_exception(err);
}
//Calculate flag
- int flag = 0;
+ int flag = map_options == default_map_options ? 0 : map_options;
if(m_mode == read_only){
flag |= SHM_RDONLY;
}
@@ -501,9 +643,17 @@ inline mapped_region::mapped_region
priv_size_from_mapping_size(buf.st_size, offset, page_offset, size);
}
+ #ifdef MAP_NOSYNC
+ #define BOOST_INTERPROCESS_MAP_NOSYNC MAP_NOSYNC
+ #else
+ #define BOOST_INTERPROCESS_MAP_NOSYNC 0
+ #endif //MAP_NOSYNC
+
//Create new mapping
int prot = 0;
- int flags = 0;
+ int flags = map_options == default_map_options ? BOOST_INTERPROCESS_MAP_NOSYNC : map_options;
+
+ #undef BOOST_INTERPROCESS_MAP_NOSYNC
switch(mode)
{
@@ -562,14 +712,110 @@ inline mapped_region::mapped_region
}
}
+inline bool mapped_region::shrink_by(std::size_t bytes, bool from_back)
+{
+ void *shrink_page_start = 0;
+ std::size_t shrink_page_bytes = 0;
+ if(m_is_xsi || !this->priv_shrink_param_check(bytes, from_back, shrink_page_start, shrink_page_bytes)){
+ return false;
+ }
+ else if(shrink_page_bytes){
+ //In UNIX we can decommit and free virtual address space.
+ return 0 == munmap(shrink_page_start, shrink_page_bytes);
+ }
+ else{
+ return true;
+ }
+}
+
inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes, bool async)
{
void *addr;
- if(!this->priv_flush_param_check(mapping_offset, addr, numbytes)){
+ if(m_is_xsi || !this->priv_flush_param_check(mapping_offset, addr, numbytes)){
return false;
}
//Flush it all
- return msync( addr, numbytes, async ? MS_ASYNC : MS_SYNC) == 0;
+ return msync(addr, numbytes, async ? MS_ASYNC : MS_SYNC) == 0;
+}
+
+inline bool mapped_region::advise(advice_types advice)
+{
+ int unix_advice = 0;
+ //Modes; 0: none, 2: posix, 1: madvise
+ const unsigned int mode_none = 0;
+ const unsigned int mode_padv = 1;
+ const unsigned int mode_madv = 2;
+ // Suppress "unused variable" warnings
+ (void)mode_padv;
+ (void)mode_madv;
+ unsigned int mode = mode_none;
+ //Choose advice either from POSIX (preferred) or native Unix
+ switch(advice){
+ case advice_normal:
+ #if defined(POSIX_MADV_NORMAL)
+ unix_advice = POSIX_MADV_NORMAL;
+ mode = mode_padv;
+ #elif defined(MADV_NORMAL)
+ unix_advice = MADV_NORMAL;
+ mode = mode_madv;
+ #endif
+ break;
+ case advice_sequential:
+ #if defined(POSIX_MADV_SEQUENTIAL)
+ unix_advice = POSIX_MADV_SEQUENTIAL;
+ mode = mode_padv;
+ #elif defined(MADV_SEQUENTIAL)
+ unix_advice = MADV_SEQUENTIAL;
+ mode = mode_madv;
+ #endif
+ break;
+ case advice_random:
+ #if defined(POSIX_MADV_RANDOM)
+ unix_advice = POSIX_MADV_RANDOM;
+ mode = mode_padv;
+ #elif defined(MADV_RANDOM)
+ unix_advice = MADV_RANDOM;
+ mode = mode_madv;
+ #endif
+ break;
+ case advice_willneed:
+ #if defined(POSIX_MADV_WILLNEED)
+ unix_advice = POSIX_MADV_WILLNEED;
+ mode = mode_padv;
+ #elif defined(MADV_WILLNEED)
+ unix_advice = MADV_WILLNEED;
+ mode = mode_madv;
+ #endif
+ break;
+ case advice_dontneed:
+ #if defined(POSIX_MADV_DONTNEED)
+ unix_advice = POSIX_MADV_DONTNEED;
+ mode = mode_padv;
+ #elif defined(MADV_DONTNEED) && defined(BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS)
+ unix_advice = MADV_DONTNEED;
+ mode = mode_madv;
+ #endif
+ break;
+ default:
+ return false;
+ }
+ switch(mode){
+ #if defined(POSIX_MADV_NORMAL)
+ case mode_padv:
+ return 0 == posix_madvise(this->priv_map_address(), this->priv_map_size(), unix_advice);
+ #endif
+ #if defined(MADV_NORMAL)
+ case mode_madv:
+ return 0 == madvise(
+ #if defined(BOOST_INTERPROCESS_MADVISE_USES_CADDR_T)
+ (caddr_t)
+ #endif
+ this->priv_map_address(), this->priv_map_size(), unix_advice);
+ #endif
+ default:
+ return false;
+
+ }
}
inline void mapped_region::priv_close()
@@ -591,7 +837,7 @@ inline void mapped_region::priv_close()
inline void mapped_region::dont_close_on_destruction()
{ m_base = 0; }
-#endif //##if (defined BOOST_INTERPROCESS_WINDOWS)
+#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
template<int dummy>
const std::size_t mapped_region::page_size_holder<dummy>::PageSize
@@ -611,7 +857,7 @@ inline void mapped_region::swap(mapped_region &other)
ipcdetail::do_swap(this->m_size, other.m_size);
ipcdetail::do_swap(this->m_page_offset, other.m_page_offset);
ipcdetail::do_swap(this->m_mode, other.m_mode);
- #if (defined BOOST_INTERPROCESS_WINDOWS)
+ #if defined (BOOST_INTERPROCESS_WINDOWS)
ipcdetail::do_swap(this->m_file_or_mapping_hnd, other.m_file_or_mapping_hnd);
#else
ipcdetail::do_swap(this->m_is_xsi, other.m_is_xsi);
@@ -623,9 +869,12 @@ struct null_mapped_region_function
{
bool operator()(void *, std::size_t , bool) const
{ return true; }
+
+ std::size_t get_min_size() const
+ { return 0; }
};
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/mem_algo/detail/mem_algo_common.hpp b/boost/interprocess/mem_algo/detail/mem_algo_common.hpp
index 91d798145b..8af256aab9 100644
--- a/boost/interprocess/mem_algo/detail/mem_algo_common.hpp
+++ b/boost/interprocess/mem_algo/detail/mem_algo_common.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP
#define BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -24,8 +24,9 @@
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/math_functions.hpp>
#include <boost/interprocess/detail/utilities.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/detail/min_max.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <algorithm>
@@ -40,6 +41,37 @@ namespace boost {
namespace interprocess {
namespace ipcdetail {
+template<class VoidPointer>
+class basic_multiallocation_chain
+ : public boost::container::container_detail::
+ basic_multiallocation_chain<VoidPointer>
+{
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain)
+ typedef boost::container::container_detail::
+ basic_multiallocation_chain<VoidPointer> base_t;
+ public:
+
+ basic_multiallocation_chain()
+ : base_t()
+ {}
+
+ basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other)
+ : base_t(::boost::move(static_cast<base_t&>(other)))
+ {}
+
+ basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other)
+ {
+ this->base_t::operator=(::boost::move(static_cast<base_t&>(other)));
+ return *this;
+ }
+
+ void *pop_front()
+ {
+ return boost::interprocess::ipcdetail::to_raw_pointer(this->base_t::pop_front());
+ }
+};
+
+
//!This class implements several allocation functions shared by different algorithms
//!(aligned allocation, multiple allocation...).
template<class MemoryAlgorithm>
@@ -81,15 +113,15 @@ class memory_algorithm_common
static size_type multiple_of_units(size_type size)
{ return get_rounded_size(size, Alignment); }
- static multiallocation_chain allocate_many
- (MemoryAlgorithm *memory_algo, size_type elem_bytes, size_type n_elements)
+ static void allocate_many
+ (MemoryAlgorithm *memory_algo, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
{
- return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, 0);
+ return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, 0, chain);
}
- static void deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain chain)
+ static void deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain)
{
- return this_type::priv_deallocate_many(memory_algo, boost::move(chain));
+ return this_type::priv_deallocate_many(memory_algo, chain);
}
static bool calculate_lcm_and_needs_backwards_lcmed
@@ -187,19 +219,20 @@ class memory_algorithm_common
return true;
}
- static multiallocation_chain allocate_many
+ static void allocate_many
( MemoryAlgorithm *memory_algo
, const size_type *elem_sizes
, size_type n_elements
- , size_type sizeof_element)
+ , size_type sizeof_element
+ , multiallocation_chain &chain)
{
- return this_type::priv_allocate_many(memory_algo, elem_sizes, n_elements, sizeof_element);
+ this_type::priv_allocate_many(memory_algo, elem_sizes, n_elements, sizeof_element, chain);
}
static void* allocate_aligned
(MemoryAlgorithm *memory_algo, size_type nbytes, size_type alignment)
{
-
+
//Ensure power of 2
if ((alignment & (alignment - size_type(1u))) != 0){
//Alignment is not power of two
@@ -215,7 +248,7 @@ class memory_algorithm_common
if(nbytes > UsableByPreviousChunk)
nbytes -= UsableByPreviousChunk;
-
+
//We can find a aligned portion if we allocate a block that has alignment
//nbytes + alignment bytes or more.
size_type minimum_allocation = max_value
@@ -255,7 +288,6 @@ class memory_algorithm_common
second->m_size = old_size - first->m_size;
BOOST_ASSERT(second->m_size >= MinBlockUnits);
memory_algo->priv_mark_new_allocated_block(first);
- //memory_algo->priv_tail_size(first, first->m_size);
memory_algo->priv_mark_new_allocated_block(second);
memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(second));
}
@@ -416,11 +448,12 @@ class memory_algorithm_common
}
private:
- static multiallocation_chain priv_allocate_many
+ static void priv_allocate_many
( MemoryAlgorithm *memory_algo
, const size_type *elem_sizes
, size_type n_elements
- , size_type sizeof_element)
+ , size_type sizeof_element
+ , multiallocation_chain &chain)
{
//Note: sizeof_element == 0 indicates that we want to
//allocate n_elements of the same size "*elem_sizes"
@@ -436,111 +469,114 @@ class memory_algorithm_common
}
else{
for(size_type i = 0; i < n_elements; ++i){
+ if(multiplication_overflows(elem_sizes[i], sizeof_element)){
+ total_request_units = 0;
+ break;
+ }
elem_units = memory_algo->priv_get_total_units(elem_sizes[i]*sizeof_element);
elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units;
+ if(sum_overflows(total_request_units, elem_units)){
+ total_request_units = 0;
+ break;
+ }
total_request_units += elem_units;
}
}
- multiallocation_chain chain;
-
- size_type low_idx = 0;
- while(low_idx < n_elements){
- size_type total_bytes = total_request_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk;
- size_type min_allocation = (!sizeof_element)
- ? elem_units
- : memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element);
- min_allocation = min_allocation*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk;
-
- size_type received_size;
- std::pair<void *, bool> ret = memory_algo->priv_allocate
- (boost::interprocess::allocate_new, min_allocation, total_bytes, received_size, 0);
- if(!ret.first){
- break;
- }
+ if(total_request_units && !multiplication_overflows(total_request_units, Alignment)){
+ size_type low_idx = 0;
+ while(low_idx < n_elements){
+ size_type total_bytes = total_request_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk;
+ size_type min_allocation = (!sizeof_element)
+ ? elem_units
+ : memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element);
+ min_allocation = min_allocation*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk;
+
+ size_type received_size;
+ std::pair<void *, bool> ret = memory_algo->priv_allocate
+ (boost::interprocess::allocate_new, min_allocation, total_bytes, received_size, 0);
+ if(!ret.first){
+ break;
+ }
- block_ctrl *block = memory_algo->priv_get_block(ret.first);
- size_type received_units = (size_type)block->m_size;
- char *block_address = reinterpret_cast<char*>(block);
+ block_ctrl *block = memory_algo->priv_get_block(ret.first);
+ size_type received_units = (size_type)block->m_size;
+ char *block_address = reinterpret_cast<char*>(block);
- size_type total_used_units = 0;
-// block_ctrl *prev_block = 0;
- while(total_used_units < received_units){
- if(sizeof_element){
- elem_units = memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element);
- elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units;
- }
- if(total_used_units + elem_units > received_units)
- break;
- total_request_units -= elem_units;
- //This is the position where the new block must be created
- block_ctrl *new_block = reinterpret_cast<block_ctrl *>(block_address);
- assert_alignment(new_block);
-
- //The last block should take all the remaining space
- if((low_idx + 1) == n_elements ||
- (total_used_units + elem_units +
- ((!sizeof_element)
- ? elem_units
- : std::max(memory_algo->priv_get_total_units(elem_sizes[low_idx+1]*sizeof_element), ptr_size_units))
- ) > received_units){
- //By default, the new block will use the rest of the buffer
- new_block->m_size = received_units - total_used_units;
- memory_algo->priv_mark_new_allocated_block(new_block);
-
- //If the remaining units are bigger than needed and we can
- //split it obtaining a new free memory block do it.
- if((received_units - total_used_units) >= (elem_units + MemoryAlgorithm::BlockCtrlUnits)){
- size_type shrunk_received;
- size_type shrunk_request = elem_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk;
- bool shrink_ok = shrink
- (memory_algo
- ,memory_algo->priv_get_user_buffer(new_block)
- ,shrunk_request
- ,shrunk_request
- ,shrunk_received);
- (void)shrink_ok;
- //Shrink must always succeed with passed parameters
- BOOST_ASSERT(shrink_ok);
- //Some sanity checks
- BOOST_ASSERT(shrunk_request == shrunk_received);
- BOOST_ASSERT(elem_units == ((shrunk_request-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits));
- //"new_block->m_size" must have been reduced to elem_units by "shrink"
- BOOST_ASSERT(new_block->m_size == elem_units);
- //Now update the total received units with the reduction
- received_units = elem_units + total_used_units;
+ size_type total_used_units = 0;
+ while(total_used_units < received_units){
+ if(sizeof_element){
+ elem_units = memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element);
+ elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units;
}
+ if(total_used_units + elem_units > received_units)
+ break;
+ total_request_units -= elem_units;
+ //This is the position where the new block must be created
+ block_ctrl *new_block = reinterpret_cast<block_ctrl *>(block_address);
+ assert_alignment(new_block);
+
+ //The last block should take all the remaining space
+ if((low_idx + 1) == n_elements ||
+ (total_used_units + elem_units +
+ ((!sizeof_element)
+ ? elem_units
+ : std::max(memory_algo->priv_get_total_units(elem_sizes[low_idx+1]*sizeof_element), ptr_size_units))
+ ) > received_units){
+ //By default, the new block will use the rest of the buffer
+ new_block->m_size = received_units - total_used_units;
+ memory_algo->priv_mark_new_allocated_block(new_block);
+
+ //If the remaining units are bigger than needed and we can
+ //split it obtaining a new free memory block do it.
+ if((received_units - total_used_units) >= (elem_units + MemoryAlgorithm::BlockCtrlUnits)){
+ size_type shrunk_received;
+ size_type shrunk_request = elem_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk;
+ bool shrink_ok = shrink
+ (memory_algo
+ ,memory_algo->priv_get_user_buffer(new_block)
+ ,shrunk_request
+ ,shrunk_request
+ ,shrunk_received);
+ (void)shrink_ok;
+ //Shrink must always succeed with passed parameters
+ BOOST_ASSERT(shrink_ok);
+ //Some sanity checks
+ BOOST_ASSERT(shrunk_request == shrunk_received);
+ BOOST_ASSERT(elem_units == ((shrunk_request-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits));
+ //"new_block->m_size" must have been reduced to elem_units by "shrink"
+ BOOST_ASSERT(new_block->m_size == elem_units);
+ //Now update the total received units with the reduction
+ received_units = elem_units + total_used_units;
+ }
+ }
+ else{
+ new_block->m_size = elem_units;
+ memory_algo->priv_mark_new_allocated_block(new_block);
+ }
+
+ block_address += new_block->m_size*Alignment;
+ total_used_units += (size_type)new_block->m_size;
+ //Check we have enough room to overwrite the intrusive pointer
+ BOOST_ASSERT((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(void_pointer));
+ void_pointer p = new(memory_algo->priv_get_user_buffer(new_block))void_pointer(0);
+ chain.push_back(p);
+ ++low_idx;
}
- else{
- new_block->m_size = elem_units;
- memory_algo->priv_mark_new_allocated_block(new_block);
- }
+ //Sanity check
+ BOOST_ASSERT(total_used_units == received_units);
+ }
- block_address += new_block->m_size*Alignment;
- total_used_units += (size_type)new_block->m_size;
- //Check we have enough room to overwrite the intrusive pointer
- BOOST_ASSERT((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(void_pointer));
- void_pointer p = new(memory_algo->priv_get_user_buffer(new_block))void_pointer(0);
- chain.push_back(p);
- ++low_idx;
- //prev_block = new_block;
+ if(low_idx != n_elements){
+ priv_deallocate_many(memory_algo, chain);
}
- //Sanity check
- BOOST_ASSERT(total_used_units == received_units);
- }
-
- if(low_idx != n_elements){
- priv_deallocate_many(memory_algo, boost::move(chain));
}
- return boost::move(chain);
}
- static void priv_deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain chain)
+ static void priv_deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain)
{
while(!chain.empty()){
- void *addr = to_raw_pointer(chain.front());
- chain.pop_front();
- memory_algo->priv_deallocate(addr);
+ memory_algo->priv_deallocate(to_raw_pointer(chain.pop_front()));
}
}
};
diff --git a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp b/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp
index e8b678d9f3..dd11bdbb50 100644
--- a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp
+++ b/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MULTI_SIMPLE_SEQ_FIT_HPP
#define BOOST_INTERPROCESS_MULTI_SIMPLE_SEQ_FIT_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -33,12 +33,12 @@ namespace interprocess {
/*!This class implements the simple sequential fit algorithm with a simply
linked list of free buffers.*/
template<class MutexFamily, class VoidPtr>
-class multi_simple_seq_fit
+class multi_simple_seq_fit
: public ipcdetail::simple_seq_fit_impl<MutexFamily, VoidPtr>
{
typedef ipcdetail::simple_seq_fit_impl<MutexFamily, VoidPtr> base_t;
public:
- /*!Constructor. "size" is the total size of the managed memory segment,
+ /*!Constructor. "size" is the total size of the managed memory segment,
"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(multi_simple_seq_fit)
offset that the allocator should not use at all.*/
multi_simple_seq_fit (size_type size, size_type extra_hdr_bytes)
diff --git a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp b/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp
index 7a2c7a83c1..c84d4e6fb7 100644
--- a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp
+++ b/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP
#define BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -84,10 +84,10 @@ class simple_seq_fit_impl
{
/*!Offset pointer to the next block.*/
block_ctrl_ptr m_next;
- /*!This block's memory size (including block_ctrl
+ /*!This block's memory size (including block_ctrl
header) in BasicSize units*/
size_type m_size;
-
+
size_type get_user_bytes() const
{ return this->m_size*Alignment - BlockCtrlBytes; }
@@ -124,7 +124,7 @@ class simple_seq_fit_impl
} m_header;
public:
- /*!Constructor. "size" is the total size of the managed memory segment,
+ /*!Constructor. "size" is the total size of the managed memory segment,
"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit_impl)
offset that the allocator should not use at all.*/
simple_seq_fit_impl (size_type size, size_type extra_hdr_bytes);
@@ -159,7 +159,7 @@ class simple_seq_fit_impl
std::pair<void *, bool>
allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
- size_type preferred_size,size_type &received_size,
+ size_type preferred_size,size_type &received_size,
void *reuse_ptr = 0, size_type backwards_multiple = 1);
/*!Returns the size of the buffer previously allocated pointed by ptr*/
@@ -170,8 +170,8 @@ class simple_seq_fit_impl
void* allocate_aligned (size_type nbytes, size_type alignment);
/*!Allocates bytes, if there is no more memory, it executes functor
- f(size_type) to allocate a new segment to manage. The functor returns
- std::pair<void*, size_type> indicating the base address and size of
+ f(size_type) to allocate a new segment to manage. The functor returns
+ std::pair<void*, size_type> indicating the base address and size of
the new segment. If the new segment can't be allocated, allocate
it will return 0.*/
void* multi_allocate(size_type nbytes);
@@ -259,7 +259,7 @@ inline simple_seq_fit_impl<MutexFamily, VoidPointer>::~simple_seq_fit_impl()
template<class MutexFamily, class VoidPointer>
inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::grow(size_type extra_size)
-{
+{
//Old highest address block's end offset
size_type old_end = m_header.m_size/Alignment*Alignment;
@@ -283,7 +283,7 @@ inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::grow(size_type extra_
template<class MutexFamily, class VoidPointer>
inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_add_segment(void *addr, size_type size)
-{
+{
//Check size
BOOST_ASSERT(!(size < MinBlockSize));
if(size < MinBlockSize)
@@ -293,7 +293,7 @@ inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_add_segment(void
new_block->m_size = size/Alignment;
new_block->m_next = 0;
//Simulate this block was previously allocated
- m_header.m_allocated += new_block->m_size*Alignment;
+ m_header.m_allocated += new_block->m_size*Alignment;
//Return block and insert it in the free block list
this->priv_deallocate(reinterpret_cast<char*>(new_block) + BlockCtrlBytes);
}
@@ -334,7 +334,7 @@ inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::clear_free_memory()
//Iterate through all free portions
do{
- //Just clear user the memory part reserved for the user
+ //Just clear user the memory part reserved for the user
std::memset( reinterpret_cast<char*>(block) + BlockCtrlBytes
, 0
, block->m_size*Alignment - BlockCtrlBytes);
@@ -381,7 +381,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
allocate(size_type nbytes)
-{
+{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
@@ -392,7 +392,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
allocate_aligned(size_type nbytes, size_type alignment)
-{
+{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
@@ -402,7 +402,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
inline std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
allocation_command (boost::interprocess::allocation_type command, size_type min_size,
- size_type preferred_size,size_type &received_size,
+ size_type preferred_size,size_type &received_size,
void *reuse_ptr, size_type backwards_multiple)
{
//-----------------------
@@ -451,11 +451,11 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
}
//Now obtain the polymorphic functor that creates
//new segments and try to allocate again.
- boost::interprocess::multi_segment_services *p_services =
+ boost::interprocess::multi_segment_services *p_services =
static_cast<boost::interprocess::multi_segment_services*>
(void_pointer::find_group_data(group));
BOOST_ASSERT(p_services);
- std::pair<void *, std::size_t> ret =
+ std::pair<void *, std::size_t> ret =
p_services->create_new_segment(MinBlockSize > nbytes ? MinBlockSize : nbytes);
if(ret.first){
priv_add_segment(ret.first, ret.second);
@@ -498,11 +498,11 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
return 0;
}
- size_type needs_backwards =
+ size_type needs_backwards =
ipcdetail::get_rounded_size(preferred_size - extra_forward, Alignment);
-
+
if(!only_preferred_backwards){
- needs_backwards =
+ needs_backwards =
max_value(ipcdetail::get_rounded_size(min_size - extra_forward, Alignment)
,min_value(prev->get_user_bytes(), needs_backwards));
}
@@ -513,15 +513,15 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
if(!priv_expand(reuse_ptr, received_size, received_size, received_size)){
BOOST_ASSERT(0);
}
-
+
//We need a minimum size to split the previous one
if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){
block_ctrl *new_block = reinterpret_cast<block_ctrl *>
(reinterpret_cast<char*>(reuse) - needs_backwards - BlockCtrlBytes);
new_block->m_next = 0;
- new_block->m_size =
+ new_block->m_size =
BlockCtrlSize + (needs_backwards + extra_forward)/Alignment;
- prev->m_size =
+ prev->m_size =
(prev->get_total_bytes() - needs_backwards)/Alignment - BlockCtrlSize;
received_size = needs_backwards + extra_forward;
m_header.m_allocated += needs_backwards + BlockCtrlBytes;
@@ -553,7 +553,7 @@ std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
,void *reuse_ptr)
{
if(command & boost::interprocess::shrink_in_place){
- bool success =
+ bool success =
this->priv_shrink(reuse_ptr, limit_size, preferred_size, received_size);
return std::pair<void *, bool> ((success ? reuse_ptr : 0), true);
}
@@ -643,7 +643,7 @@ inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *
}
template<class MutexFamily, class VoidPointer>
-inline
+inline
std::pair<typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *
,typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *>
simple_seq_fit_impl<MutexFamily, VoidPointer>::
@@ -724,7 +724,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::
//We can fill expand. Merge both blocks,
block->m_next = next_block->m_next;
block->m_size = merged_size;
-
+
//Find the previous free block of next_block
block_ctrl *prev = &m_header.m_root;
while(ipcdetail::to_raw_pointer(prev->m_next) != next_block){
@@ -733,7 +733,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::
//Now insert merged block in the free list
//This allows reusing allocation logic in this function
- m_header.m_allocated -= old_block_size*Alignment;
+ m_header.m_allocated -= old_block_size*Alignment;
prev->m_next = block;
//Now use check and allocate to do the allocation logic
@@ -747,7 +747,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::
BOOST_ASSERT(0);
return false;
}
- return true;
+ return true;
}
template<class MutexFamily, class VoidPointer>
@@ -805,13 +805,13 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::
//Now deallocate the new block to insert it in the free list
this->priv_deallocate(reinterpret_cast<char*>(block)+BlockCtrlBytes);
- return true;
+ return true;
}
template<class MutexFamily, class VoidPointer>
inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
priv_allocate_aligned(size_type nbytes, size_type alignment)
-{
+{
//Ensure power of 2
if ((alignment & (alignment - size_type(1u))) != 0){
//Alignment is not power of two
@@ -823,8 +823,8 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
if(alignment <= Alignment){
return priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first;
}
-
- size_type request =
+
+ size_type request =
nbytes + alignment + MinBlockSize*Alignment - BlockCtrlBytes;
void *buffer = priv_allocate(boost::interprocess::allocate_new, request, request, ignore).first;
if(!buffer)
@@ -835,7 +835,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
char *aligned_portion = reinterpret_cast<char*>
(reinterpret_cast<size_type>(static_cast<char*>(buffer) + alignment - 1) & -alignment);
- char *pos = ((aligned_portion - reinterpret_cast<char*>(buffer)) >= (MinBlockSize*Alignment)) ?
+ char *pos = ((aligned_portion - reinterpret_cast<char*>(buffer)) >= (MinBlockSize*Alignment)) ?
aligned_portion : (aligned_portion + alignment);
block_ctrl *first = reinterpret_cast<block_ctrl*>
@@ -867,7 +867,7 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_check_and_allocate
bool found = false;
if (block->m_size > upper_nunits){
- //This block is bigger than needed, split it in
+ //This block is bigger than needed, split it in
//two blocks, the first's size will be (block->m_size-units)
//the second's size (units)
size_type total_size = block->m_size;
@@ -918,7 +918,7 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr)
//Let's get free block list. List is always sorted
//by memory address to allow block merging.
- //Pointer next always points to the first
+ //Pointer next always points to the first
//(lower address) block
block_ctrl_ptr prev = &m_header.m_root;
block_ctrl_ptr pos = m_header.m_root.m_next;
@@ -934,9 +934,9 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr)
size_type total_size = Alignment*block->m_size;
BOOST_ASSERT(m_header.m_allocated >= total_size);
-
+
//Update used memory count
- m_header.m_allocated -= total_size;
+ m_header.m_allocated -= total_size;
//Let's find the previous and the next block of the block to deallocate
//This ordering comparison must be done with original pointers
@@ -949,7 +949,7 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr)
//Try to combine with upper block
if ((reinterpret_cast<char*>(ipcdetail::to_raw_pointer(block))
- + Alignment*block->m_size) ==
+ + Alignment*block->m_size) ==
reinterpret_cast<char*>(ipcdetail::to_raw_pointer(pos))){
block->m_size += pos->m_size;
@@ -961,7 +961,7 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr)
//Try to combine with lower block
if ((reinterpret_cast<char*>(ipcdetail::to_raw_pointer(prev))
- + Alignment*prev->m_size) ==
+ + Alignment*prev->m_size) ==
reinterpret_cast<char*>(ipcdetail::to_raw_pointer(block))){
prev->m_size += block->m_size;
prev->m_next = block->m_next;
diff --git a/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp b/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp
index c36916b72f..fa0e9caeb7 100644
--- a/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp
+++ b/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP
#define BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -60,7 +60,7 @@ class simple_seq_fit_impl
simple_seq_fit_impl();
simple_seq_fit_impl(const simple_seq_fit_impl &);
simple_seq_fit_impl &operator=(const simple_seq_fit_impl &);
-
+
typedef typename boost::intrusive::
pointer_traits<VoidPointer>::template
rebind_pointer<char>::type char_ptr;
@@ -80,13 +80,12 @@ class simple_seq_fit_impl
private:
class block_ctrl;
+ friend class block_ctrl;
+
typedef typename boost::intrusive::
pointer_traits<VoidPointer>::template
rebind_pointer<block_ctrl>::type block_ctrl_ptr;
- class block_ctrl;
- friend class block_ctrl;
-
//!Block control structure
class block_ctrl
{
@@ -96,7 +95,7 @@ class simple_seq_fit_impl
//!This block's memory size (including block_ctrl
//!header) in BasicSize units
size_type m_size;
-
+
size_type get_user_bytes() const
{ return this->m_size*Alignment - BlockCtrlBytes; }
@@ -142,32 +141,30 @@ class simple_seq_fit_impl
//!Allocates bytes, returns 0 if there is not more memory
void* allocate (size_type nbytes);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Multiple element allocation, same size
- multiallocation_chain
- allocate_many(size_type elem_bytes, size_type num_elements)
+ void allocate_many(size_type elem_bytes, size_type num_elements, multiallocation_chain &chain)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
- return algo_impl_t::allocate_many(this, elem_bytes, num_elements);
+ algo_impl_t::allocate_many(this, elem_bytes, num_elements, chain);
}
//!Multiple element allocation, different size
- multiallocation_chain
- allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element)
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
- return algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element);
+ algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, chain);
}
//!Multiple element deallocation
- void deallocate_many(multiallocation_chain chain);
+ void deallocate_many(multiallocation_chain &chain);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Deallocates previously allocated bytes
void deallocate (void *addr);
@@ -283,7 +280,7 @@ class simple_seq_fit_impl
void priv_mark_new_allocated_block(block_ctrl *block);
public:
- static const size_type Alignment = ::boost::alignment_of< ::boost::detail::max_align>::value;
+ static const size_type Alignment = ::boost::alignment_of< ::boost::detail::max_align>::value;
private:
static const size_type BlockCtrlBytes = ipcdetail::ct_rounded_size<sizeof(block_ctrl), Alignment>::value;
static const size_type BlockCtrlUnits = BlockCtrlBytes/Alignment;
@@ -331,11 +328,11 @@ simple_seq_fit_impl<MutexFamily, VoidPointer>
template<class MutexFamily, class VoidPointer>
inline simple_seq_fit_impl<MutexFamily, VoidPointer>::
- simple_seq_fit_impl(size_type size, size_type extra_hdr_bytes)
+ simple_seq_fit_impl(size_type segment_size, size_type extra_hdr_bytes)
{
//Initialize sizes and counters
m_header.m_allocated = 0;
- m_header.m_size = size;
+ m_header.m_size = segment_size;
m_header.m_extra_hdr_bytes = extra_hdr_bytes;
//Initialize pointers
@@ -344,7 +341,7 @@ inline simple_seq_fit_impl<MutexFamily, VoidPointer>::
m_header.m_root.m_next = reinterpret_cast<block_ctrl*>
((reinterpret_cast<char*>(this) + block1_off));
algo_impl_t::assert_alignment(ipcdetail::to_raw_pointer(m_header.m_root.m_next));
- m_header.m_root.m_next->m_size = (size - block1_off)/Alignment;
+ m_header.m_root.m_next->m_size = (segment_size - block1_off)/Alignment;
m_header.m_root.m_next->m_next = &m_header.m_root;
}
@@ -426,7 +423,7 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::shrink_to_fit()
(void)addr;
BOOST_ASSERT(addr);
BOOST_ASSERT(received_size == last_units*Alignment - AllocatedCtrlBytes);
-
+
//Shrink it
m_header.m_size /= Alignment;
m_header.m_size -= last->m_size;
@@ -462,16 +459,16 @@ void *simple_seq_fit_impl<MutexFamily, VoidPointer>::
}
template<class MutexFamily, class VoidPointer>
-inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_add_segment(void *addr, size_type size)
-{
+inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_add_segment(void *addr, size_type segment_size)
+{
algo_impl_t::assert_alignment(addr);
//Check size
- BOOST_ASSERT(!(size < MinBlockSize));
- if(size < MinBlockSize)
+ BOOST_ASSERT(!(segment_size < MinBlockSize));
+ if(segment_size < MinBlockSize)
return;
//Construct big block using the new segment
block_ctrl *new_block = static_cast<block_ctrl *>(addr);
- new_block->m_size = size/Alignment;
+ new_block->m_size = segment_size/Alignment;
new_block->m_next = 0;
//Simulate this block was previously allocated
m_header.m_allocated += new_block->m_size*Alignment;
@@ -523,7 +520,7 @@ inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::zero_free_memory()
//Iterate through all free portions
do{
- //Just clear user the memory part reserved for the user
+ //Just clear user the memory part reserved for the user
std::memset( priv_get_user_buffer(block)
, 0
, block->get_user_bytes());
@@ -583,7 +580,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
allocate_aligned(size_type nbytes, size_type alignment)
-{
+{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
@@ -653,8 +650,7 @@ inline std::pair<void*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::size_type
-simple_seq_fit_impl<MutexFamily, VoidPointer>::
- size(const void *ptr) const
+simple_seq_fit_impl<MutexFamily, VoidPointer>::size(const void *ptr) const
{
//We need no synchronization since this block is not going
//to be modified
@@ -698,7 +694,7 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
size_type needs_backwards =
ipcdetail::get_rounded_size(preferred_size - extra_forward, Alignment);
-
+
if(!only_preferred_backwards){
max_value(ipcdetail::get_rounded_size(min_size - extra_forward, Alignment)
,min_value(prev->get_user_bytes(), needs_backwards));
@@ -710,7 +706,7 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
if(!priv_expand(reuse_ptr, received_size, received_size, received_size)){
BOOST_ASSERT(0);
}
-
+
//We need a minimum size to split the previous one
if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){
block_ctrl *new_block = reinterpret_cast<block_ctrl*>
@@ -744,15 +740,13 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::
- deallocate_many(typename simple_seq_fit_impl<MutexFamily, VoidPointer>::multiallocation_chain chain)
+ deallocate_many(typename simple_seq_fit_impl<MutexFamily, VoidPointer>::multiallocation_chain &chain)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
while(!chain.empty()){
- void *addr = chain.front();
- chain.pop_front();
- this->priv_deallocate(addr);
+ this->priv_deallocate(to_raw_pointer(chain.pop_front()));
}
}
@@ -969,7 +963,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::
//We can fill expand. Merge both blocks,
block->m_next = next_block->m_next;
block->m_size = merged_size;
-
+
//Find the previous free block of next_block
block_ctrl *prev = &m_header.m_root;
while(ipcdetail::to_raw_pointer(prev->m_next) != next_block){
@@ -978,7 +972,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::
//Now insert merged block in the free list
//This allows reusing allocation logic in this function
- m_header.m_allocated -= old_block_size*Alignment;
+ m_header.m_allocated -= old_block_size*Alignment;
prev->m_next = block;
//Now use check and allocate to do the allocation logic
@@ -992,7 +986,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::
BOOST_ASSERT(0);
return false;
}
- return true;
+ return true;
}
template<class MutexFamily, class VoidPointer> inline
@@ -1071,9 +1065,9 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr)
size_type total_size = Alignment*block->m_size;
BOOST_ASSERT(m_header.m_allocated >= total_size);
-
+
//Update used memory count
- m_header.m_allocated -= total_size;
+ m_header.m_allocated -= total_size;
//Let's find the previous and the next block of the block to deallocate
//This ordering comparison must be done with original pointers
diff --git a/boost/interprocess/mem_algo/rbtree_best_fit.hpp b/boost/interprocess/mem_algo/rbtree_best_fit.hpp
index 7ccc642e29..fb04889c17 100644
--- a/boost/interprocess/mem_algo/rbtree_best_fit.hpp
+++ b/boost/interprocess/mem_algo/rbtree_best_fit.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP
#define BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -31,11 +31,12 @@
#include <boost/interprocess/detail/math_functions.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
-#include <boost/type_traits.hpp>
#include <algorithm>
#include <utility>
#include <climits>
@@ -65,7 +66,7 @@ namespace interprocess {
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
class rbtree_best_fit
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
rbtree_best_fit();
rbtree_best_fit(const rbtree_best_fit &);
@@ -81,20 +82,19 @@ class rbtree_best_fit
pointer_traits<VoidPointer>::template
rebind_pointer<char>::type char_ptr;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Shared mutex family used for the rest of the Interprocess framework
typedef MutexFamily mutex_family;
//!Pointer type to be used with the rest of the Interprocess framework
typedef VoidPointer void_pointer;
- typedef boost::container::container_detail::
- basic_multiallocation_chain<VoidPointer> multiallocation_chain;
+ typedef ipcdetail::basic_multiallocation_chain<VoidPointer> multiallocation_chain;
typedef typename boost::intrusive::pointer_traits<char_ptr>::difference_type difference_type;
typedef typename boost::make_unsigned<difference_type>::type size_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
@@ -132,7 +132,7 @@ class rbtree_best_fit
{ return size < block.m_size; }
bool operator()(const block_ctrl &block, size_type size) const
- { return block.m_size < size; }
+ { return block.m_size < size; }
};
//!Shared mutex to protect memory allocate/deallocate
@@ -141,6 +141,7 @@ class rbtree_best_fit
<block_ctrl, bi::base_hook<TreeHook> >::type Imultiset;
typedef typename Imultiset::iterator imultiset_iterator;
+ typedef typename Imultiset::const_iterator imultiset_const_iterator;
//!This struct includes needed data and derives from
//!mutex_type to allow EBO when using null mutex_type
@@ -157,11 +158,11 @@ class rbtree_best_fit
} m_header;
friend class ipcdetail::memory_algorithm_common<rbtree_best_fit>;
-
+
typedef ipcdetail::memory_algorithm_common<rbtree_best_fit> algo_impl_t;
public:
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Constructor. "size" is the total size of the managed memory segment,
//!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(rbtree_best_fit)
@@ -179,34 +180,32 @@ class rbtree_best_fit
//!Allocates bytes, returns 0 if there is not more memory
void* allocate (size_type nbytes);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Experimental. Dont' use
//!Multiple element allocation, same size
- multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements)
+ void allocate_many(size_type elem_bytes, size_type num_elements, multiallocation_chain &chain)
{
-
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//-----------------------
- return algo_impl_t::allocate_many(this, elem_bytes, num_elements);
+ algo_impl_t::allocate_many(this, elem_bytes, num_elements, chain);
}
//!Multiple element allocation, different size
- multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element)
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
{
-
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//-----------------------
- return algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element);
+ algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, chain);
}
//!Multiple element allocation, different size
- void deallocate_many(multiallocation_chain chain);
+ void deallocate_many(multiallocation_chain &chain);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Deallocates previously allocated bytes
void deallocate (void *addr);
@@ -253,7 +252,7 @@ class rbtree_best_fit
//!Alignment must be power of 2
void* allocate_aligned (size_type nbytes, size_type alignment);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
static size_type priv_first_block_offset_from_this(const void *this_ptr, size_type extra_hdr_bytes);
@@ -339,7 +338,7 @@ class rbtree_best_fit
void priv_add_segment(void *addr, size_type size);
public:
-
+
static const size_type Alignment = !MemAlignment
? size_type(::boost::alignment_of< ::boost::detail::max_align>::value)
: size_type(MemAlignment)
@@ -362,12 +361,12 @@ class rbtree_best_fit
//Make sure the maximum alignment is power of two
BOOST_STATIC_ASSERT((0 == (Alignment & (Alignment - size_type(1u)))));
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
static const size_type PayloadPerAllocation = AllocatedCtrlBytes - UsableByPreviousChunk;
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::size_type
@@ -385,16 +384,16 @@ inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::size_ty
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
- priv_add_segment(void *addr, size_type size)
-{
+ priv_add_segment(void *addr, size_type segment_size)
+{
//Check alignment
algo_impl_t::check_alignment(addr);
//Check size
- BOOST_ASSERT(size >= (BlockCtrlBytes + EndCtrlBlockBytes));
+ BOOST_ASSERT(segment_size >= (BlockCtrlBytes + EndCtrlBlockBytes));
//Initialize the first big block and the "end" node
block_ctrl *first_big_block = new(addr)block_ctrl;
- first_big_block->m_size = size/Alignment - EndCtrlBlockUnits;
+ first_big_block->m_size = segment_size/Alignment - EndCtrlBlockUnits;
BOOST_ASSERT(first_big_block->m_size >= BlockCtrlUnits);
//The "end" node is just a node of size 0 with the "end" bit set
@@ -451,18 +450,18 @@ inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_c
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
inline rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
- rbtree_best_fit(size_type size, size_type extra_hdr_bytes)
+ rbtree_best_fit(size_type segment_size, size_type extra_hdr_bytes)
{
//Initialize the header
m_header.m_allocated = 0;
- m_header.m_size = size;
+ m_header.m_size = segment_size;
m_header.m_extra_hdr_bytes = extra_hdr_bytes;
//Now write calculate the offset of the first big block that will
//cover the whole segment
- BOOST_ASSERT(get_min_size(extra_hdr_bytes) <= size);
+ BOOST_ASSERT(get_min_size(extra_hdr_bytes) <= segment_size);
size_type block1_off = priv_first_block_offset_from_this(this, extra_hdr_bytes);
- priv_add_segment(reinterpret_cast<char*>(this) + block1_off, size - block1_off);
+ priv_add_segment(reinterpret_cast<char*>(this) + block1_off, segment_size - block1_off);
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
@@ -570,7 +569,7 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::shrink_to_fit()
size_type shrunk_border_offset = (size_type)(reinterpret_cast<char*>(last_block) -
reinterpret_cast<char*>(this)) + EndCtrlBlockBytes;
-
+
block_ctrl *new_end_block = last_block;
algo_impl_t::assert_alignment(new_end_block);
@@ -672,7 +671,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
inline void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
allocate(size_type nbytes)
-{
+{
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//-----------------------
@@ -816,7 +815,6 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
block_ctrl *reuse = priv_get_block(reuse_ptr);
//Sanity check
- //BOOST_ASSERT(reuse->m_size == priv_tail_size(reuse));
algo_impl_t::assert_alignment(reuse);
block_ctrl *prev_block;
@@ -851,7 +849,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
if(!priv_expand(reuse_ptr, received_size, received_size, received_size2)){
BOOST_ASSERT(0);
}
- BOOST_ASSERT(received_size = received_size2);
+ BOOST_ASSERT(received_size == received_size2);
}
//We need a minimum size to split the previous one
if(prev_block->m_size >= (needs_backwards_aligned/Alignment + BlockCtrlUnits)){
@@ -884,7 +882,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
received_size = needs_backwards_aligned + received_size;
m_header.m_allocated += needs_backwards_aligned;
-
+
//Check alignment
algo_impl_t::assert_alignment(new_block);
@@ -930,12 +928,12 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
inline void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
- deallocate_many(typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::multiallocation_chain chain)
+ deallocate_many(typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::multiallocation_chain &chain)
{
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//-----------------------
- algo_impl_t::deallocate_many(this, boost::move(chain));
+ algo_impl_t::deallocate_many(this, chain);
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
@@ -1043,8 +1041,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
//The block must be marked as allocated and the sizes must be equal
BOOST_ASSERT(priv_is_allocated_block(block));
- //BOOST_ASSERT(old_block_units == priv_tail_size(block));
-
+
//Put this to a safe value
received_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk;
if(received_size >= preferred_size || received_size >= min_size)
@@ -1208,9 +1205,6 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_is_allocated_
(void)next_block_prev_allocated;
BOOST_ASSERT(allocated == next_block_prev_allocated);
}
- else{
- block = block;
- }
#endif
return allocated;
}
@@ -1228,9 +1222,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_is_prev_alloc
block_ctrl *prev = priv_prev_block(block);
(void)prev;
BOOST_ASSERT(!prev->m_allocated);
- }
- else{
- block = block;
+ BOOST_ASSERT(prev->m_size == block->m_prev_size);
}
#endif
return false;
@@ -1284,7 +1276,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_check_and_al
imultiset_iterator it_hint;
if(it_old == m_header.m_imultiset.begin()
- || (--imultiset_iterator(it_old))->m_size < rem_block->m_size){
+ || (--imultiset_iterator(it_old))->m_size <= rem_block->m_size){
//option a: slow but secure
//m_header.m_imultiset.insert(m_header.m_imultiset.erase(it_old), *rem_block);
//option b: Construct an empty node and swap
@@ -1298,7 +1290,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_check_and_al
m_header.m_imultiset.erase(it_old);
m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *rem_block);
}
-
+
}
else if (block->m_size >= nunits){
m_header.m_imultiset.erase(it_old);
@@ -1318,7 +1310,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_check_and_al
//Clear the memory occupied by the tree hook, since this won't be
//cleared with zero_free_memory
TreeHook *t = static_cast<TreeHook*>(block);
- //Just clear the memory part reserved for the user
+ //Just clear the memory part reserved for the user
std::size_t tree_hook_offset_in_block = (char*)t - (char*)block;
//volatile char *ptr =
char *ptr = reinterpret_cast<char*>(block)+tree_hook_offset_in_block;
@@ -1344,10 +1336,9 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_deallocate(vo
if(!addr) return;
block_ctrl *block = priv_get_block(addr);
-
+
//The blocks must be marked as allocated and the sizes must be equal
BOOST_ASSERT(priv_is_allocated_block(block));
-// BOOST_ASSERT(block->m_size == priv_tail_size(block));
//Check if alignment and block size are right
algo_impl_t::assert_alignment(addr);
@@ -1362,42 +1353,44 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_deallocate(vo
block_ctrl *block_to_insert = block;
//Get the next block
- block_ctrl *next_block = priv_next_block(block);
- bool merge_with_prev = !priv_is_prev_allocated(block);
- bool merge_with_next = !priv_is_allocated_block(next_block);
+ block_ctrl *const next_block = priv_next_block(block);
+ const bool merge_with_prev = !priv_is_prev_allocated(block);
+ const bool merge_with_next = !priv_is_allocated_block(next_block);
//Merge logic. First just update block sizes, then fix free blocks tree
if(merge_with_prev || merge_with_next){
//Merge if the previous is free
if(merge_with_prev){
//Get the previous block
- block_ctrl *prev_block = priv_prev_block(block);
- prev_block->m_size += block->m_size;
- BOOST_ASSERT(prev_block->m_size >= BlockCtrlUnits);
- block_to_insert = prev_block;
+ block_to_insert = priv_prev_block(block);
+ block_to_insert->m_size += block->m_size;
+ BOOST_ASSERT(block_to_insert->m_size >= BlockCtrlUnits);
}
//Merge if the next is free
if(merge_with_next){
block_to_insert->m_size += next_block->m_size;
BOOST_ASSERT(block_to_insert->m_size >= BlockCtrlUnits);
- if(merge_with_prev)
- m_header.m_imultiset.erase(Imultiset::s_iterator_to(*next_block));
+ const imultiset_iterator next_it = Imultiset::s_iterator_to(*next_block);
+ if(merge_with_prev){
+ m_header.m_imultiset.erase(next_it);
+ }
+ else{
+ m_header.m_imultiset.replace_node(next_it, *block_to_insert);
+ }
}
- bool only_merge_next = !merge_with_prev && merge_with_next;
- imultiset_iterator free_block_to_check_it
- (Imultiset::s_iterator_to(only_merge_next ? *next_block : *block_to_insert));
- imultiset_iterator was_bigger_it(free_block_to_check_it);
-
//Now try to shortcut erasure + insertion (O(log(N))) with
//a O(1) operation if merging does not alter tree positions
- if(++was_bigger_it != m_header.m_imultiset.end() &&
- block_to_insert->m_size > was_bigger_it->m_size ){
- m_header.m_imultiset.erase(free_block_to_check_it);
- m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *block_to_insert);
+ const imultiset_iterator block_to_check_it = Imultiset::s_iterator_to(*block_to_insert);
+ imultiset_const_iterator next_to_check_it(block_to_check_it), end_it(m_header.m_imultiset.end());
+
+ if(++next_to_check_it != end_it && block_to_insert->m_size > next_to_check_it->m_size){
+ //Block is bigger than next, so move it
+ m_header.m_imultiset.erase(block_to_check_it);
+ m_header.m_imultiset.insert(end_it, *block_to_insert);
}
- else if(only_merge_next){
- m_header.m_imultiset.replace_node(free_block_to_check_it, *block_to_insert);
+ else{
+ //Block size increment didn't violate tree invariants so there is nothing to fix
}
}
else{
@@ -1406,7 +1399,7 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_deallocate(vo
priv_mark_as_free_block(block_to_insert);
}
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/mem_algo/simple_seq_fit.hpp b/boost/interprocess/mem_algo/simple_seq_fit.hpp
index 1085ca00ac..aaa5d37497 100644
--- a/boost/interprocess/mem_algo/simple_seq_fit.hpp
+++ b/boost/interprocess/mem_algo/simple_seq_fit.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP
#define BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -34,9 +34,9 @@ template<class MutexFamily, class VoidPointer>
class simple_seq_fit
: public ipcdetail::simple_seq_fit_impl<MutexFamily, VoidPointer>
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef ipcdetail::simple_seq_fit_impl<MutexFamily, VoidPointer> base_t;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
typedef typename base_t::size_type size_type;
@@ -44,8 +44,8 @@ class simple_seq_fit
//!Constructor. "size" is the total size of the managed memory segment,
//!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit)
//!offset that the allocator should not use at all.*/
- simple_seq_fit (size_type size, size_type extra_hdr_bytes)
- : base_t(size, extra_hdr_bytes){}
+ simple_seq_fit(size_type segment_size, size_type extra_hdr_bytes)
+ : base_t(segment_size, extra_hdr_bytes){}
};
} //namespace interprocess {
diff --git a/boost/interprocess/offset_ptr.hpp b/boost/interprocess/offset_ptr.hpp
index ac8da2c292..5f523ce521 100644
--- a/boost/interprocess/offset_ptr.hpp
+++ b/boost/interprocess/offset_ptr.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP
#define BOOST_INTERPROCESS_OFFSET_PTR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -26,6 +26,7 @@
#include <ostream>
#include <istream>
#include <iterator>
+#include <iostream>
#include <boost/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
@@ -35,6 +36,8 @@
namespace boost {
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
//Predeclarations
template <class T>
struct has_trivial_constructor;
@@ -42,22 +45,209 @@ struct has_trivial_constructor;
template <class T>
struct has_trivial_destructor;
+#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
namespace interprocess {
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+namespace ipcdetail {
+
+ template<class OffsetType, std::size_t OffsetAlignment>
+ union offset_ptr_internal
+ {
+ explicit offset_ptr_internal(OffsetType off)
+ : m_offset(off)
+ {}
+ OffsetType m_offset; //Distance between this object and pointee address
+ typename ::boost::aligned_storage
+ < sizeof(OffsetType)
+ , (OffsetAlignment == offset_type_alignment) ?
+ ::boost::alignment_of<OffsetType>::value : OffsetAlignment
+ >::type alignment_helper;
+ };
+
+ //Note: using the address of a local variable to point to another address
+ //is not standard conforming and this can be optimized-away by the compiler.
+ //Non-inlining is a method to remain illegal but correct
+
+ //Undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_XXX if your compiler can inline
+ //this code without breaking the library
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // offset_ptr_to_raw_pointer
+ //
+ ////////////////////////////////////////////////////////////////////////
+ #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
+ #if defined(_MSC_VER) && (_MSC_VER >= 1800) && (defined(_M_AMD64) || defined(_M_X64))
+ //Visual 2013 x64 optimizes more than we desire, so disable branchless option
+ #else
+ #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
+ #endif
+ template<int Dummy>
+ #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
+ BOOST_INTERPROCESS_NEVER_INLINE
+ #elif defined(NDEBUG)
+ inline
+ #endif
+ void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, std::size_t offset)
+ {
+ typedef pointer_size_t_caster<void*> caster_t;
+ #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
+ if(offset == 1){
+ return 0;
+ }
+ else{
+ const caster_t caster((void*)this_ptr);
+ return caster_t(caster.size() + offset).pointer();
+ }
+ #else
+ const caster_t caster((void*)this_ptr);
+ std::size_t target_offset = caster.size() + offset;
+ std::size_t mask = -std::size_t(offset != 1);
+ target_offset &= mask;
+ return caster_t(target_offset).pointer();
+ #endif
+ }
+
+ #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
+ #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
+ #endif
+ #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
+ #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
+ #endif
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // offset_ptr_to_offset
+ //
+ ////////////////////////////////////////////////////////////////////////
+ #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
+ //Branchless seems slower in x86
+ #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
+
+ template<int Dummy>
+ #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
+ BOOST_INTERPROCESS_NEVER_INLINE
+ #elif defined(NDEBUG)
+ inline
+ #endif
+ std::size_t offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr)
+ {
+ typedef pointer_size_t_caster<void*> caster_t;
+ #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
+ //offset == 1 && ptr != 0 is not legal for this pointer
+ if(!ptr){
+ return 1;
+ }
+ else{
+ const caster_t this_caster((void*)this_ptr);
+ const caster_t ptr_caster((void*)ptr);
+ std::size_t offset = ptr_caster.size() - this_caster.size();
+ BOOST_ASSERT(offset != 1);
+ return offset;
+ }
+ #else
+ const caster_t this_caster((void*)this_ptr);
+ const caster_t ptr_caster((void*)ptr);
+ //std::size_t other = -std::size_t(ptr != 0);
+ //std::size_t offset = (ptr_caster.size() - this_caster.size()) & other;
+ //return offset + !other;
+ //
+ std::size_t offset = (ptr_caster.size() - this_caster.size() - 1) & -std::size_t(ptr != 0);
+ return ++offset;
+ #endif
+ }
+
+ #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
+ #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
+ #endif
+ #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
+ #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
+ #endif
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // offset_ptr_to_offset_from_other
+ //
+ ////////////////////////////////////////////////////////////////////////
+ #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
+ //Branchless seems slower in x86
+ #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
+
+ template<int Dummy>
+ #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
+ BOOST_INTERPROCESS_NEVER_INLINE
+ #elif defined(NDEBUG)
+ inline
+ #endif
+ std::size_t offset_ptr_to_offset_from_other
+ (const volatile void *this_ptr, const volatile void *other_ptr, std::size_t other_offset)
+ {
+ typedef pointer_size_t_caster<void*> caster_t;
+ #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
+ if(other_offset == 1){
+ return 1;
+ }
+ else{
+ const caster_t this_caster((void*)this_ptr);
+ const caster_t other_caster((void*)other_ptr);
+ std::size_t offset = other_caster.size() - this_caster.size() + other_offset;
+ BOOST_ASSERT(offset != 1);
+ return offset;
+ }
+ #else
+ const caster_t this_caster((void*)this_ptr);
+ const caster_t other_caster((void*)other_ptr);
+ return ((other_caster.size() - this_caster.size()) & -std::size_t(other_offset != 1)) + other_offset;
+ #endif
+ }
+
+ #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
+ #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
+ #endif
+ #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
+ #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
+ #endif
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Let's assume cast to void and cv cast don't change any target address
+ //
+ ////////////////////////////////////////////////////////////////////////
+ template<class From, class To>
+ struct offset_ptr_maintains_address
+ {
+ static const bool value = ipcdetail::is_cv_same<From, To>::value
+ || ipcdetail::is_cv_same<void, To>::value;
+ };
+
+} //namespace ipcdetail {
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
//!A smart pointer that stores the offset between between the pointer and the
//!the object it points. This allows offset allows special properties, since
//!the pointer is independent from the address address of the pointee, if the
//!pointer and the pointee are still separated by the same offset. This feature
//!converts offset_ptr in a smart pointer that can be placed in shared memory and
//!memory mapped files mapped in different addresses in every process.
+//!
+//! \tparam PointedType The type of the pointee.
+//! \tparam DifferenceType A signed integer type that can represent the arithmetic operations on the pointer
+//! \tparam OffsetType An unsigned integer type that can represent the
+//! distance between two pointers reinterpret_cast-ed as unsigned integers. In general this type
+//! should be at least of the same size of std::uintptr_t. In some systems it's possible to communicate
+//! between 32 and 64 bit processes using 64 bit offsets.
+//! \tparam OffsetAlignment Alignment of the OffsetType stored inside. In some systems might be necessary
+//! to align it to 64 bits in order to communicate 32 and 64 bit processes using 64 bit offsets.
template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
class offset_ptr
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> self_t;
void unspecified_bool_type_func() const {}
typedef void (self_t::*unspecified_bool_type)() const;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
typedef PointedType element_type;
@@ -74,69 +264,111 @@ class offset_ptr
public: //Public Functions
+ //!Default constructor (null pointer).
+ //!Never throws.
+ offset_ptr()
+ : internal(1)
+ {}
+
//!Constructor from raw pointer (allows "0" pointer conversion).
//!Never throws.
- offset_ptr(pointer ptr = 0) { this->set_offset(ptr); }
+ offset_ptr(pointer ptr)
+ : internal(static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(ptr, this)))
+ {}
//!Constructor from other pointer.
//!Never throws.
template <class T>
offset_ptr( T *ptr
, typename ipcdetail::enable_if< ipcdetail::is_convertible<T*, PointedType*> >::type * = 0)
- { this->set_offset(static_cast<PointedType*>(ptr)); }
+ : internal(static_cast<OffsetType>
+ (ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr), this)))
+ {}
//!Constructor from other offset_ptr
//!Never throws.
offset_ptr(const offset_ptr& ptr)
- { this->set_offset(ptr.get()); }
+ : internal(static_cast<OffsetType>
+ (ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset)))
+ {}
//!Constructor from other offset_ptr. If pointers of pointee types are
//!convertible, offset_ptrs will be convertibles. Never throws.
- template<class T2, class P2, class O2, std::size_t A2>
- offset_ptr( const offset_ptr<T2, P2, O2, A2> &ptr
- , typename ipcdetail::enable_if< ipcdetail::is_convertible<T2*, PointedType*> >::type * = 0)
- { this->set_offset(static_cast<PointedType*>(ptr.get())); }
+ template<class T2>
+ offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
+ #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ , typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value
+ && ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
+ >::type * = 0
+ #endif
+ )
+ : internal(static_cast<OffsetType>
+ (ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset())))
+ {}
+
+ #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+ //!Constructor from other offset_ptr. If pointers of pointee types are
+ //!convertible, offset_ptrs will be convertibles. Never throws.
+ template<class T2>
+ offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
+ , typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value
+ && !ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
+ >::type * = 0)
+ : internal(static_cast<OffsetType>
+ (ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr.get()), this)))
+ {}
+
+ #endif
//!Emulates static_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::static_cast_tag)
- { this->set_offset(static_cast<PointedType*>(r.get())); }
+ : internal(static_cast<OffsetType>
+ (ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(r.get()), this)))
+ {}
//!Emulates const_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::const_cast_tag)
- { this->set_offset(const_cast<PointedType*>(r.get())); }
+ : internal(static_cast<OffsetType>
+ (ipcdetail::offset_ptr_to_offset<0>(const_cast<PointedType*>(r.get()), this)))
+ {}
//!Emulates dynamic_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::dynamic_cast_tag)
- { this->set_offset(dynamic_cast<PointedType*>(r.get())); }
+ : internal(static_cast<OffsetType>
+ (ipcdetail::offset_ptr_to_offset<0>(dynamic_cast<PointedType*>(r.get()), this)))
+ {}
//!Emulates reinterpret_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::reinterpret_cast_tag)
- { this->set_offset(reinterpret_cast<PointedType*>(r.get())); }
+ : internal(static_cast<OffsetType>
+ (ipcdetail::offset_ptr_to_offset<0>(reinterpret_cast<PointedType*>(r.get()), this)))
+ {}
//!Obtains raw pointer from offset.
//!Never throws.
- pointer get()const
- { return this->to_raw_pointer(); }
+ pointer get() const
+ { return (pointer)ipcdetail::offset_ptr_to_raw_pointer<0>(this, this->internal.m_offset); }
offset_type get_offset() const
- { return internal.m_offset; }
+ { return this->internal.m_offset; }
//!Pointer-like -> operator. It can return 0 pointer.
//!Never throws.
- pointer operator->() const
+ pointer operator->() const
{ return this->get(); }
//!Dereferencing operator, if it is a null offset_ptr behavior
//! is undefined. Never throws.
- reference operator* () const
+ reference operator* () const
{
pointer p = this->get();
reference r = *p;
@@ -145,26 +377,56 @@ class offset_ptr
//!Indexing operator.
//!Never throws.
- template<class T>
- reference operator[](T idx) const
+ reference operator[](difference_type idx) const
{ return this->get()[idx]; }
//!Assignment from pointer (saves extra conversion).
//!Never throws.
offset_ptr& operator= (pointer from)
- { this->set_offset(from); return *this; }
+ {
+ this->internal.m_offset =
+ static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(from, this));
+ return *this;
+ }
//!Assignment from other offset_ptr.
//!Never throws.
- offset_ptr& operator= (const offset_ptr & pt)
- { pointer p(pt.get()); (void)p; this->set_offset(p); return *this; }
+ offset_ptr& operator= (const offset_ptr & ptr)
+ {
+ this->internal.m_offset =
+ static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset));
+ return *this;
+ }
//!Assignment from related offset_ptr. If pointers of pointee types
//! are assignable, offset_ptrs will be assignable. Never throws.
- template<class T2, class P2, class O2, std::size_t A2>
- typename ipcdetail::enable_if<ipcdetail::is_convertible<T2*, PointedType*>, offset_ptr&>::type
- operator= (const offset_ptr<T2, P2, O2, A2> & ptr)
- { this->set_offset(static_cast<PointedType*>(ptr.get())); return *this; }
+ template<class T2>
+ #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value
+ && ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
+ , offset_ptr&>::type
+ #else
+ offset_ptr&
+ #endif
+ operator= (const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr)
+ {
+ this->internal.m_offset =
+ static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset()));
+ return *this;
+ }
+
+ #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ template<class T2>
+ typename ipcdetail::enable_if_c<ipcdetail::is_convertible<T2*, PointedType*>::value
+ && !ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
+ , offset_ptr&>::type
+ operator= (const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr)
+ {
+ this->internal.m_offset =
+ static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr.get()), this));
+ return *this;
+ }
+ #endif
//!offset_ptr += difference_type.
//!Never throws.
@@ -173,8 +435,7 @@ class offset_ptr
//!offset_ptr -= difference_type.
//!Never throws.
- template<class T>
- offset_ptr &operator-= (T offset)
+ offset_ptr &operator-= (difference_type offset)
{ this->dec_offset(offset * sizeof (PointedType)); return *this; }
//!++offset_ptr.
@@ -185,7 +446,11 @@ class offset_ptr
//!offset_ptr++.
//!Never throws.
offset_ptr operator++ (int)
- { offset_ptr temp(*this); ++*this; return temp; }
+ {
+ offset_ptr tmp(*this);
+ this->inc_offset(sizeof (PointedType));
+ return tmp;
+ }
//!--offset_ptr.
//!Never throws.
@@ -195,17 +460,21 @@ class offset_ptr
//!offset_ptr--.
//!Never throws.
offset_ptr operator-- (int)
- { offset_ptr temp(*this); --*this; return temp; }
+ {
+ offset_ptr tmp(*this);
+ this->dec_offset(sizeof (PointedType));
+ return tmp;
+ }
//!safe bool conversion operator.
//!Never throws.
- operator unspecified_bool_type() const
- { return this->get()? &self_t::unspecified_bool_type_func : 0; }
+ operator unspecified_bool_type() const
+ { return this->internal.m_offset != 1? &self_t::unspecified_bool_type_func : 0; }
//!Not operator. Not needed in theory, but improves portability.
//!Never throws
bool operator! () const
- { return this->get() == 0; }
+ { return this->internal.m_offset == 1; }
//!Compatibility with pointer_traits
//!
@@ -220,23 +489,23 @@ class offset_ptr
//!difference_type + offset_ptr
//!operation
- friend offset_ptr operator+(difference_type diff, const offset_ptr& right)
- { offset_ptr tmp(right); tmp += diff; return tmp; }
+ friend offset_ptr operator+(difference_type diff, offset_ptr right)
+ { right += diff; return right; }
//!offset_ptr + difference_type
//!operation
- friend offset_ptr operator+(const offset_ptr& left, difference_type diff)
- { offset_ptr tmp(left); tmp += diff; return tmp; }
+ friend offset_ptr operator+(offset_ptr left, difference_type diff)
+ { left += diff; return left; }
//!offset_ptr - diff
//!operation
- friend offset_ptr operator-(const offset_ptr &left, difference_type diff)
- { offset_ptr tmp(left); tmp -= diff; return tmp; }
+ friend offset_ptr operator-(offset_ptr left, difference_type diff)
+ { left -= diff; return left; }
//!offset_ptr - diff
//!operation
- friend offset_ptr operator-(difference_type diff, const offset_ptr &right)
- { offset_ptr tmp(right); tmp -= diff; return tmp; }
+ friend offset_ptr operator-(difference_type diff, offset_ptr right)
+ { right -= diff; return right; }
//!offset_ptr - offset_ptr
//!operation
@@ -308,65 +577,15 @@ class offset_ptr
}
private:
- /// @cond
-
- //Note: using the address of a local variable to point to another address
- //is not standard conforming and this can be optimized-away by the compiler.
- //Non-inlining is a method to remain illegal and correct
- #if defined(_MSC_VER)
- __declspec(noinline) //this workaround is needed for MSVC compilers
- #elif defined (__GNUC__)//this workaround is needed for GCC
- __attribute__((__noinline__))
- #endif
- void set_offset(const PointedType *ptr)
- {
- #if defined (__GNUC__)
- //asm(""); //Prevents the function to be optimized-away (provokes an special "side-effect")
- #endif
- //offset == 1 && ptr != 0 is not legal for this pointer
- if(!ptr){
- internal.m_offset = 1;
- }
- else{
- internal.m_offset = (OffsetType)((const char*)ptr - (const char*)(this));
- BOOST_ASSERT(internal.m_offset != 1);
- }
- }
-
- #if defined(_MSC_VER) && (_MSC_VER >= 1400)
- __declspec(noinline)
- #elif defined (__GNUC__)
- __attribute__((__noinline__))
- #endif
- PointedType * to_raw_pointer() const
- {
- #if defined (__GNUC__)
- //asm(""); //Prevents the function to be optimized-away (provokes an special "side-effect")
- #endif
- return static_cast<PointedType *>(
- static_cast<void*>(
- (internal.m_offset == 1) ?
- 0 :
- (const_cast<char*>(reinterpret_cast<const char*>(this)) + internal.m_offset)
- )
- );
- }
-
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
void inc_offset(DifferenceType bytes)
{ internal.m_offset += bytes; }
void dec_offset(DifferenceType bytes)
{ internal.m_offset -= bytes; }
- union internal_type{
- OffsetType m_offset; //Distance between this object and pointee address
- typename ::boost::aligned_storage
- < sizeof(OffsetType)
- , (OffsetAlignment == offset_type_alignment) ?
- ::boost::alignment_of<OffsetType>::value : OffsetAlignment
- >::type alignment_helper;
- } internal;
- /// @endcond
+ ipcdetail::offset_ptr_internal<OffsetType, OffsetAlignment> internal;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!operator<<
@@ -387,41 +606,41 @@ inline std::basic_istream<E, T> & operator>>
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
static_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
-{
+{
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
- (r, boost::interprocess::ipcdetail::static_cast_tag());
+ (r, boost::interprocess::ipcdetail::static_cast_tag());
}
//!Simulation of const_cast between pointers. Never throws.
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
const_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
-{
+{
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
- (r, boost::interprocess::ipcdetail::const_cast_tag());
+ (r, boost::interprocess::ipcdetail::const_cast_tag());
}
//!Simulation of dynamic_cast between pointers. Never throws.
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
dynamic_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
-{
+{
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
- (r, boost::interprocess::ipcdetail::dynamic_cast_tag());
+ (r, boost::interprocess::ipcdetail::dynamic_cast_tag());
}
//!Simulation of reinterpret_cast between pointers. Never throws.
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
reinterpret_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
-{
+{
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
- (r, boost::interprocess::ipcdetail::reinterpret_cast_tag());
+ (r, boost::interprocess::ipcdetail::reinterpret_cast_tag());
}
} //namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!has_trivial_constructor<> == true_type specialization for optimizations
template <class T, class P, class O, std::size_t A>
@@ -437,22 +656,22 @@ struct has_trivial_destructor< boost::interprocess::offset_ptr<T, P, O, A> >
static const bool value = true;
};
-//#if !defined(_MSC_VER) || (_MSC_VER >= 1400)
+
namespace interprocess {
-//#endif
+
//!to_raw_pointer() enables boost::mem_fn to recognize offset_ptr.
//!Never throws.
template <class T, class P, class O, std::size_t A>
inline T * to_raw_pointer(boost::interprocess::offset_ptr<T, P, O, A> const & p)
-{ return p.get(); }
-//#if !defined(_MSC_VER) || (_MSC_VER >= 1400)
+{ return ipcdetail::to_raw_pointer(p); }
+
} //namespace interprocess
-//#endif
-/// @endcond
+
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace boost {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace boost{
@@ -479,28 +698,34 @@ struct pointer_plus_bits;
template<class T, class P, class O, std::size_t A, std::size_t NumBits>
struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
{
- typedef boost::interprocess::offset_ptr<T, P, O, A> pointer;
+ typedef boost::interprocess::offset_ptr<T, P, O, A> pointer;
+ typedef ::boost::interprocess::pointer_size_t_caster<T*> caster_t;
//Bits are stored in the lower bits of the pointer except the LSB,
//because this bit is used to represent the null pointer.
- static const std::size_t Mask = ((std::size_t(1) << NumBits)-1)<<1u;
+ static const std::size_t Mask = ((std::size_t(1) << NumBits) - 1) << 1u;
static pointer get_pointer(const pointer &n)
- { return reinterpret_cast<T*>(std::size_t(n.get()) & ~std::size_t(Mask)); }
+ {
+ caster_t caster(n.get());
+ return pointer(caster_t(caster.size() & ~Mask).pointer());
+ }
- static void set_pointer(pointer &n, pointer p)
+ static void set_pointer(pointer &n, const pointer &p)
{
- std::size_t pint = std::size_t(p.get());
- BOOST_ASSERT(0 == (std::size_t(pint) & Mask));
- n = reinterpret_cast<T*>(pint | (std::size_t(n.get()) & std::size_t(Mask)));
+ caster_t n_caster(n.get());
+ caster_t p_caster(p.get());
+ BOOST_ASSERT(0 == (p_caster.size() & Mask));
+ n = caster_t(p_caster.size() | (n_caster.size() & Mask)).pointer();
}
static std::size_t get_bits(const pointer &n)
- { return(std::size_t(n.get()) & std::size_t(Mask)) >> 1u; }
+ { return (caster_t(n.get()).size() & Mask) >> 1u; }
static void set_bits(pointer &n, std::size_t b)
{
BOOST_ASSERT(b < (std::size_t(1) << NumBits));
- n = reinterpret_cast<T*>(std::size_t(get_pointer(n).get()) | (b << 1u));
+ caster_t n_caster(n.get());
+ n = caster_t((n_caster.size() & ~Mask) | (b << 1u)).pointer();
}
};
@@ -510,8 +735,6 @@ struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
template<class T, class U>
struct pointer_to_other;
-
-
//Backwards compatibility with pointer_to_other
template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment, class U>
struct pointer_to_other
@@ -521,7 +744,7 @@ struct pointer_to_other
};
} //namespace boost{
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
#include <boost/interprocess/detail/config_end.hpp>
diff --git a/boost/interprocess/permissions.hpp b/boost/interprocess/permissions.hpp
index 745f8a8e0f..49ddbd09a7 100644
--- a/boost/interprocess/permissions.hpp
+++ b/boost/interprocess/permissions.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,9 +11,9 @@
#ifndef BOOST_INTERPROCESS_PERMISSIONS_HPP
#define BOOST_INTERPROCESS_PERMISSIONS_HPP
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-#if defined (_MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -27,7 +27,7 @@
#endif
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!\file
//!Describes permissions class
@@ -35,7 +35,7 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if defined(BOOST_INTERPROCESS_WINDOWS)
@@ -54,14 +54,14 @@ winapi::interprocess_all_access_security unrestricted_permissions_holder<Dummy>:
#endif //defined BOOST_INTERPROCESS_WINDOWS
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!The permissions class represents permissions to be set to shared memory or
//!files, that can be constructed form usual permission representations:
//!a SECURITY_ATTRIBUTES pointer in windows or ORed rwx chmod integer in UNIX.
class permissions
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if defined(BOOST_INTERPROCESS_WINDOWS)
typedef void* os_permissions_type;
@@ -70,7 +70,7 @@ class permissions
#endif
os_permissions_type m_perm;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructs a permissions object from a user provided os-dependent
@@ -90,26 +90,22 @@ class permissions
//!for UNIX.
void set_default()
{
- /// @cond
#if defined (BOOST_INTERPROCESS_WINDOWS)
m_perm = 0;
#else
m_perm = 0644;
#endif
- /// @endcond
}
//!Sets permissions to unrestricted access:
//!A null DACL for windows or 0666 for UNIX.
void set_unrestricted()
{
- /// @cond
#if defined (BOOST_INTERPROCESS_WINDOWS)
m_perm = &ipcdetail::unrestricted_permissions_holder<0>::unrestricted;
#else
m_perm = 0666;
#endif
- /// @endcond
}
//!Sets permissions from a user provided os-dependent
diff --git a/boost/interprocess/segment_manager.hpp b/boost/interprocess/segment_manager.hpp
index 8680a953e2..87c0041cf4 100644
--- a/boost/interprocess/segment_manager.hpp
+++ b/boost/interprocess/segment_manager.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
#define BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -32,7 +32,7 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/smart_ptr/deleter.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <cstddef> //std::size_t
#include <string> //char_traits
@@ -69,15 +69,15 @@ class segment_manager_base
typedef typename MemoryAlgorithm::void_pointer void_pointer;
typedef typename MemoryAlgorithm::mutex_family mutex_family;
typedef MemoryAlgorithm memory_algorithm;
-
- /// @cond
-
+
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
//Experimental. Don't use
typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain;
typedef typename MemoryAlgorithm::difference_type difference_type;
typedef typename MemoryAlgorithm::size_type size_type;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!This constant indicates the payload size
//!associated with each allocation of the memory algorithm
@@ -94,8 +94,8 @@ class segment_manager_base
//!dynamic allocation
//!
//!Can throw
- segment_manager_base(size_type size, size_type reserved_bytes)
- : MemoryAlgorithm(size, reserved_bytes)
+ segment_manager_base(size_type sz, size_type reserved_bytes)
+ : MemoryAlgorithm(sz, reserved_bytes)
{
BOOST_ASSERT((sizeof(segment_manager_base<MemoryAlgorithm>) == sizeof(MemoryAlgorithm)));
}
@@ -120,52 +120,53 @@ class segment_manager_base
void * allocate (size_type nbytes, std::nothrow_t)
{ return MemoryAlgorithm::allocate(nbytes); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Experimental. Dont' use.
- //!Allocates n_elements of
- //!elem_size bytes. Throws bad_alloc on failure.
- multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements)
+ //!Allocates n_elements of elem_bytes bytes.
+ //!Throws bad_alloc on failure. chain.size() is not increased on failure.
+ void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
{
- multiallocation_chain mem(MemoryAlgorithm::allocate_many(elem_bytes, num_elements));
- if(mem.empty()) throw bad_alloc();
- return boost::move(mem);
+ size_type prev_size = chain.size();
+ MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain);
+ if(!elem_bytes || chain.size() == prev_size){
+ throw bad_alloc();
+ }
}
- //!Allocates n_elements, each one of
- //!element_lenghts[i]*sizeof_element bytes. Throws bad_alloc on failure.
- multiallocation_chain allocate_many
- (const size_type *element_lenghts, size_type n_elements, size_type sizeof_element = 1)
+ //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
+ //!Throws bad_alloc on failure. chain.size() is not increased on failure.
+ void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
{
- multiallocation_chain mem(MemoryAlgorithm::allocate_many(element_lenghts, n_elements, sizeof_element));
- if(mem.empty()) throw bad_alloc();
- return boost::move(mem);
+ size_type prev_size = chain.size();
+ MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, chain);
+ if(!sizeof_element || chain.size() == prev_size){
+ throw bad_alloc();
+ }
}
- //!Allocates n_elements of
- //!elem_size bytes. Returns a default constructed iterator on failure.
- multiallocation_chain allocate_many
- (size_type elem_bytes, size_type num_elements, std::nothrow_t)
- { return MemoryAlgorithm::allocate_many(elem_bytes, num_elements); }
+ //!Allocates n_elements of elem_bytes bytes.
+ //!Non-throwing version. chain.size() is not increased on failure.
+ void allocate_many(std::nothrow_t, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
+ { MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); }
//!Allocates n_elements, each one of
- //!element_lenghts[i]*sizeof_element bytes.
- //!Returns a default constructed iterator on failure.
- multiallocation_chain allocate_many
- (const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, std::nothrow_t)
- { return MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element); }
+ //!element_lengths[i]*sizeof_element bytes.
+ //!Non-throwing version. chain.size() is not increased on failure.
+ void allocate_many(std::nothrow_t, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
+ { MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, chain); }
- //!Deallocates elements pointed by the
- //!multiallocation iterator range.
- void deallocate_many(multiallocation_chain chain)
- { MemoryAlgorithm::deallocate_many(boost::move(chain)); }
+ //!Deallocates all elements contained in chain.
+ //!Never throws.
+ void deallocate_many(multiallocation_chain &chain)
+ { MemoryAlgorithm::deallocate_many(chain); }
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc
//!on failure
void * allocate(size_type nbytes)
- {
+ {
void * ret = MemoryAlgorithm::allocate(nbytes);
if(!ret)
throw bad_alloc();
@@ -180,13 +181,15 @@ class segment_manager_base
//!Allocates nbytes bytes. This function is only used in
//!single-segment management. Throws bad_alloc when fails
void * allocate_aligned(size_type nbytes, size_type alignment)
- {
+ {
void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
if(!ret)
throw bad_alloc();
return ret;
}
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
template<class T>
std::pair<T *, bool>
allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
@@ -214,6 +217,8 @@ class segment_manager_base
return ret;
}
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
//!Deallocates the bytes allocated with allocate/allocate_many()
//!pointed by addr
void deallocate (void *addr)
@@ -248,7 +253,7 @@ class segment_manager_base
size_type size(const void *ptr) const
{ return MemoryAlgorithm::size(ptr); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
protected:
void * prot_anonymous_construct
(size_type num, bool dothrow, ipcdetail::in_place_interface &table)
@@ -293,7 +298,7 @@ class segment_manager_base
void prot_anonymous_destroy(const void *object, ipcdetail::in_place_interface &table)
{
- //Get control data from associated with this object
+ //Get control data from associated with this object
typedef ipcdetail::block_header<size_type> block_header_t;
block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment);
@@ -312,7 +317,7 @@ class segment_manager_base
table.destroy_n(const_cast<void*>(object), ctrl_data->m_value_bytes/table.size, destroyed);
this->deallocate(ctrl_data);
}
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!This object is placed in the beginning of memory segment and
@@ -337,26 +342,26 @@ template<class CharType
class segment_manager
: public segment_manager_base<MemoryAlgorithm>
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
segment_manager();
segment_manager(const segment_manager &);
segment_manager &operator=(const segment_manager &);
- typedef segment_manager_base<MemoryAlgorithm> Base;
- /// @endcond
+ typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_t;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
- typedef MemoryAlgorithm memory_algorithm;
- typedef typename Base::void_pointer void_pointer;
- typedef typename Base::size_type size_type;
- typedef typename Base::difference_type difference_type;
- typedef CharType char_type;
+ typedef MemoryAlgorithm memory_algorithm;
+ typedef typename segment_manager_base_t::void_pointer void_pointer;
+ typedef typename segment_manager_base_t::size_type size_type;
+ typedef typename segment_manager_base_t::difference_type difference_type;
+ typedef CharType char_type;
typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
- static const size_type PayloadPerAllocation = Base::PayloadPerAllocation;
+ static const size_type PayloadPerAllocation = segment_manager_base_t::PayloadPerAllocation;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef ipcdetail::block_header<size_type> block_header_t;
typedef ipcdetail::index_config<CharType, MemoryAlgorithm> index_config_named;
@@ -376,16 +381,16 @@ class segment_manager
typedef ipcdetail::segment_manager_iterator_transform
<typename unique_index_t::const_iterator
,is_intrusive_index<index_type>::value> unique_transform;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
- typedef typename Base::mutex_family mutex_family;
+ typedef typename segment_manager_base_t::mutex_family mutex_family;
typedef transform_iterator
<typename named_index_t::const_iterator, named_transform> const_named_iterator;
typedef transform_iterator
<typename unique_index_t::const_iterator, unique_transform> const_unique_iterator;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Constructor proxy object definition helper class
template<class T>
@@ -401,52 +406,44 @@ class segment_manager
typedef ipcdetail::named_proxy<segment_manager, T, true> type;
};
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Constructor of the segment manager
//!"size" is the size of the memory segment where
//!the segment manager is being constructed.
//!Can throw
- segment_manager(size_type size)
- : Base(size, priv_get_reserved_bytes())
- , m_header(static_cast<Base*>(get_this_pointer()))
+ explicit segment_manager(size_type segment_size)
+ : segment_manager_base_t(segment_size, priv_get_reserved_bytes())
+ , m_header(static_cast<segment_manager_base_t*>(get_this_pointer()))
{
(void) anonymous_instance; (void) unique_instance;
- BOOST_ASSERT(static_cast<const void*>(this) == static_cast<const void*>(static_cast<Base*>(this)));
+ //Check EBO is applied, it's required
+ const void * const this_addr = this;
+ const void *const segm_addr = static_cast<segment_manager_base_t*>(this);
+ (void)this_addr; (void)segm_addr;
+ BOOST_ASSERT( this_addr == segm_addr);
}
- //!Tries to find a previous named allocation. Returns the address
- //!and the object count. On failure the first member of the
- //!returned pair is 0.
- template <class T>
- std::pair<T*, size_type> find (const CharType* name)
- { return this->priv_find_impl<T>(name, true); }
-
- //!Tries to find a previous unique allocation. Returns the address
+ //!Tries to find a previous named/unique allocation. Returns the address
//!and the object count. On failure the first member of the
//!returned pair is 0.
template <class T>
- std::pair<T*, size_type> find (const ipcdetail::unique_instance_t* name)
+ std::pair<T*, size_type> find (char_ptr_holder_t name)
{ return this->priv_find_impl<T>(name, true); }
- //!Tries to find a previous named allocation. Returns the address
+ //!Tries to find a previous named/unique allocation. Returns the address
//!and the object count. On failure the first member of the
//!returned pair is 0. This search is not mutex-protected!
+ //!Use it only inside atomic_func() calls, where the internal mutex
+ //!is guaranteed to be locked.
template <class T>
- std::pair<T*, size_type> find_no_lock (const CharType* name)
- { return this->priv_find_impl<T>(name, false); }
-
- //!Tries to find a previous unique allocation. Returns the address
- //!and the object count. On failure the first member of the
- //!returned pair is 0. This search is not mutex-protected!
- template <class T>
- std::pair<T*, size_type> find_no_lock (const ipcdetail::unique_instance_t* name)
+ std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name)
{ return this->priv_find_impl<T>(name, false); }
//!Returns throwing "construct" proxy
//!object
template <class T>
- typename construct_proxy<T>::type
+ typename construct_proxy<T>::type
construct(char_ptr_holder_t name)
{ return typename construct_proxy<T>::type (this, name, false, true); }
@@ -466,27 +463,27 @@ class segment_manager
//!Returns no throwing "search or construct"
//!proxy object
template <class T>
- typename construct_proxy<T>::type
+ typename construct_proxy<T>::type
find_or_construct(char_ptr_holder_t name, std::nothrow_t)
{ return typename construct_proxy<T>::type (this, name, true, false); }
//!Returns throwing "construct from iterators" proxy object
template <class T>
- typename construct_iter_proxy<T>::type
+ typename construct_iter_proxy<T>::type
construct_it(char_ptr_holder_t name)
{ return typename construct_iter_proxy<T>::type (this, name, false, true); }
//!Returns throwing "search or construct from iterators"
//!proxy object
template <class T>
- typename construct_iter_proxy<T>::type
+ typename construct_iter_proxy<T>::type
find_or_construct_it(char_ptr_holder_t name)
{ return typename construct_iter_proxy<T>::type (this, name, true, true); }
//!Returns no throwing "construct from iterators"
//!proxy object
template <class T>
- typename construct_iter_proxy<T>::type
+ typename construct_iter_proxy<T>::type
construct_it(char_ptr_holder_t name, std::nothrow_t)
{ return typename construct_iter_proxy<T>::type (this, name, false, false); }
@@ -499,7 +496,7 @@ class segment_manager
//!Calls object function blocking recursive interprocess_mutex and guarantees that
//!no new named_alloc or destroy will be executed by any process while
- //!executing the object function call*/
+ //!executing the object function call
template <class Func>
void atomic_func(Func &f)
{ scoped_lock<rmutex> guard(m_header); f(); }
@@ -522,28 +519,26 @@ class segment_manager
}
}
- //!Destroys a previously created unique instance.
+ //!Destroys a previously created named/unique instance.
//!Returns false if the object was not present.
template <class T>
- bool destroy(const ipcdetail::unique_instance_t *)
+ bool destroy(char_ptr_holder_t name)
{
+ BOOST_ASSERT(!name.is_anonymous());
ipcdetail::placement_destroy<T> dtor;
- return this->priv_generic_named_destroy<char>
- (typeid(T).name(), m_header.m_unique_index, dtor, is_intrusive_t());
- }
- //!Destroys the named object with
- //!the given name. Returns false if that object can't be found.
- template <class T>
- bool destroy(const CharType *name)
- {
- ipcdetail::placement_destroy<T> dtor;
- return this->priv_generic_named_destroy<CharType>
- (name, m_header.m_named_index, dtor, is_intrusive_t());
+ if(name.is_unique()){
+ return this->priv_generic_named_destroy<char>
+ ( typeid(T).name(), m_header.m_unique_index , dtor, is_intrusive_t());
+ }
+ else{
+ return this->priv_generic_named_destroy<CharType>
+ ( name.get(), m_header.m_named_index, dtor, is_intrusive_t());
+ }
}
//!Destroys an anonymous, unique or named object
- //!using it's address
+ //!using its address
template <class T>
void destroy_ptr(const T *p)
{
@@ -575,18 +570,18 @@ class segment_manager
//!creation of "num" named objects in the managed memory segment.
//!Can throw boost::interprocess::bad_alloc if there is no enough memory.
void reserve_named_objects(size_type num)
- {
+ {
//-------------------------------
scoped_lock<rmutex> guard(m_header);
//-------------------------------
- m_header.m_named_index.reserve(num);
+ m_header.m_named_index.reserve(num);
}
//!Preallocates needed index resources to optimize the
//!creation of "num" unique objects in the managed memory segment.
//!Can throw boost::interprocess::bad_alloc if there is no enough memory.
void reserve_unique_objects(size_type num)
- {
+ {
//-------------------------------
scoped_lock<rmutex> guard(m_header);
//-------------------------------
@@ -596,38 +591,38 @@ class segment_manager
//!Calls shrink_to_fit in both named and unique object indexes
//!to try to free unused memory from those indexes.
void shrink_to_fit_indexes()
- {
+ {
//-------------------------------
scoped_lock<rmutex> guard(m_header);
//-------------------------------
- m_header.m_named_index.shrink_to_fit();
- m_header.m_unique_index.shrink_to_fit();
+ m_header.m_named_index.shrink_to_fit();
+ m_header.m_unique_index.shrink_to_fit();
}
//!Returns the number of named objects stored in
//!the segment.
size_type get_num_named_objects()
- {
+ {
//-------------------------------
scoped_lock<rmutex> guard(m_header);
//-------------------------------
- return m_header.m_named_index.size();
+ return m_header.m_named_index.size();
}
//!Returns the number of unique objects stored in
//!the segment.
size_type get_num_unique_objects()
- {
+ {
//-------------------------------
scoped_lock<rmutex> guard(m_header);
//-------------------------------
- return m_header.m_unique_index.size();
+ return m_header.m_unique_index.size();
}
//!Obtains the minimum size needed by the
//!segment manager
static size_type get_min_size()
- { return Base::get_min_size(priv_get_reserved_bytes()); }
+ { return segment_manager_base_t::get_min_size(priv_get_reserved_bytes()); }
//!Returns a constant iterator to the beginning of the information about
//!the named allocations performed in this segment manager
@@ -684,14 +679,14 @@ class segment_manager
typedef boost::interprocess::deleter<T, segment_manager> type;
};
- //!Returns an instance of the default allocator for type T
- //!initialized that allocates memory from this segment manager.
+ //!Returns an instance of the default deleter for type T
+ //!that will delete an object constructed in this segment manager.
template<class T>
typename deleter<T>::type
get_deleter()
{ return typename deleter<T>::type(this); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Generic named/anonymous new function. Offers all the possibilities,
//!such as throwing, search before creating, and the constructor is
@@ -713,20 +708,20 @@ class segment_manager
//!returned pair is 0.
template <class T>
std::pair<T*, size_type> priv_find_impl (const CharType* name, bool lock)
- {
+ {
//The name can't be null, no anonymous object can be found by name
BOOST_ASSERT(name != 0);
ipcdetail::placement_destroy<T> table;
- size_type size;
+ size_type sz;
void *ret;
if(name == reinterpret_cast<const CharType*>(-1)){
- ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, size, is_intrusive_t(), lock);
+ ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, sz, is_intrusive_t(), lock);
}
else{
- ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, size, is_intrusive_t(), lock);
+ ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, sz, is_intrusive_t(), lock);
}
- return std::pair<T*, size_type>(static_cast<T*>(ret), size);
+ return std::pair<T*, size_type>(static_cast<T*>(ret), sz);
}
//!Tries to find a previous unique allocation. Returns the address
@@ -741,11 +736,8 @@ class segment_manager
return std::pair<T*, size_type>(static_cast<T*>(ret), size);
}
- void *priv_generic_construct(const CharType *name,
- size_type num,
- bool try2find,
- bool dothrow,
- ipcdetail::in_place_interface &table)
+ void *priv_generic_construct
+ (const CharType *name, size_type num, bool try2find, bool dothrow, ipcdetail::in_place_interface &table)
{
void *ret;
//Security overflow check
@@ -799,13 +791,13 @@ class segment_manager
static const CharType *priv_get_instance_name(block_header_t *ctrl_data)
{
boost::interprocess::allocation_type type = ctrl_data->alloc_type();
- if(type != named_type){
+ if(type == anonymous_type){
BOOST_ASSERT((type == anonymous_type && ctrl_data->m_num_char == 0) ||
(type == unique_type && ctrl_data->m_num_char != 0) );
return 0;
}
CharType *name = static_cast<CharType*>(ctrl_data->template name<CharType>());
-
+
//Sanity checks
BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharType));
BOOST_ASSERT(ctrl_data->m_num_char == std::char_traits<CharType>::length(name));
@@ -831,8 +823,8 @@ class segment_manager
static size_type priv_get_reserved_bytes()
{
//Get the number of bytes until the end of (*this)
- //beginning in the end of the Base base.
- return sizeof(segment_manager) - sizeof(Base);
+ //beginning in the end of the segment_manager_base_t base.
+ return sizeof(segment_manager) - sizeof(segment_manager_base_t);
}
template <class CharT>
@@ -840,13 +832,10 @@ class segment_manager
(const CharT* name,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::in_place_interface &table,
- size_type &length,
- ipcdetail::true_ is_intrusive,
- bool use_lock)
+ size_type &length, ipcdetail::true_ is_intrusive, bool use_lock)
{
(void)is_intrusive;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
- typedef ipcdetail::index_key<CharT, void_pointer> index_key_t;
typedef typename index_type::iterator index_it;
//-------------------------------
@@ -880,9 +869,7 @@ class segment_manager
(const CharT* name,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::in_place_interface &table,
- size_type &length,
- ipcdetail::false_ is_intrusive,
- bool use_lock)
+ size_type &length, ipcdetail::false_ is_intrusive, bool use_lock)
{
(void)is_intrusive;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
@@ -918,8 +905,7 @@ class segment_manager
bool priv_generic_named_destroy
(block_header_t *block_header,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
- ipcdetail::in_place_interface &table,
- ipcdetail::true_ is_node_index)
+ ipcdetail::in_place_interface &table, ipcdetail::true_ is_node_index)
{
(void)is_node_index;
typedef typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator index_it;
@@ -943,15 +929,13 @@ class segment_manager
template <class CharT>
bool priv_generic_named_destroy(const CharT *name,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
- ipcdetail::in_place_interface &table,
- ipcdetail::true_ is_intrusive_index)
+ ipcdetail::in_place_interface &table, ipcdetail::true_ is_intrusive_index)
{
(void)is_intrusive_index;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
- typedef ipcdetail::index_key<CharT, void_pointer> index_key_t;
typedef typename index_type::iterator index_it;
typedef typename index_type::value_type intrusive_value_type;
-
+
//-------------------------------
scoped_lock<rmutex> guard(m_header);
//-------------------------------
@@ -972,7 +956,7 @@ class segment_manager
void *memory = iv;
void *values = ctrl_data->value();
std::size_t num = ctrl_data->m_value_bytes/table.size;
-
+
//Sanity check
BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
@@ -1061,21 +1045,17 @@ class segment_manager
}
//Call destructors and free memory
- std::size_t destroyed;
+ std::size_t destroyed;
table.destroy_n(values, num, destroyed);
this->deallocate(memory);
return true;
}
template<class CharT>
- void * priv_generic_named_construct(unsigned char type,
- const CharT *name,
- size_type num,
- bool try2find,
- bool dothrow,
- ipcdetail::in_place_interface &table,
- IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
- ipcdetail::true_ is_intrusive)
+ void * priv_generic_named_construct
+ (unsigned char type, const CharT *name, size_type num, bool try2find,
+ bool dothrow, ipcdetail::in_place_interface &table,
+ IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::true_ is_intrusive)
{
(void)is_intrusive;
std::size_t namelen = std::char_traits<CharT>::length(name);
@@ -1184,7 +1164,7 @@ class segment_manager
//the memory allocation as the intrusive value is built in that
//memory
value_eraser<index_type> v_eraser(index, it);
-
+
//Construct array, this can throw
ipcdetail::array_construct(ptr, num, table);
@@ -1197,14 +1177,10 @@ class segment_manager
//!Generic named new function for
//!named functions
template<class CharT>
- void * priv_generic_named_construct(unsigned char type,
- const CharT *name,
- size_type num,
- bool try2find,
- bool dothrow,
- ipcdetail::in_place_interface &table,
- IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
- ipcdetail::false_ is_intrusive)
+ void * priv_generic_named_construct
+ (unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow,
+ ipcdetail::in_place_interface &table,
+ IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::false_ is_intrusive)
{
(void)is_intrusive;
std::size_t namelen = std::char_traits<CharT>::length(name);
@@ -1346,14 +1322,14 @@ class segment_manager
{
named_index_t m_named_index;
unique_index_t m_unique_index;
-
- header_t(Base *restricted_segment_mngr)
- : m_named_index (restricted_segment_mngr)
- , m_unique_index(restricted_segment_mngr)
+
+ header_t(segment_manager_base_t *segment_mngr_base)
+ : m_named_index (segment_mngr_base)
+ , m_unique_index(segment_mngr_base)
{}
} m_header;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
diff --git a/boost/interprocess/shared_memory_object.hpp b/boost/interprocess/shared_memory_object.hpp
index f3bc7ba173..59ea343264 100644
--- a/boost/interprocess/shared_memory_object.hpp
+++ b/boost/interprocess/shared_memory_object.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,15 +11,19 @@
#ifndef BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP
#define BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
-#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/detail/shared_dir_helpers.hpp>
#include <boost/interprocess/permissions.hpp>
#include <cstddef>
#include <string>
@@ -51,10 +55,10 @@ namespace interprocess {
//!create mapped regions from the mapped files
class shared_memory_object
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable and non-assignable
BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_memory_object)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Default constructor. Represents an empty shared_memory_object.
@@ -81,16 +85,17 @@ class shared_memory_object
//!Does not throw
shared_memory_object(BOOST_RV_REF(shared_memory_object) moved)
: m_handle(file_handle_t(ipcdetail::invalid_file()))
+ , m_mode(read_only)
{ this->swap(moved); }
//!Moves the ownership of "moved"'s shared memory to *this.
//!After the call, "moved" does not represent any shared memory.
//!Does not throw
shared_memory_object &operator=(BOOST_RV_REF(shared_memory_object) moved)
- {
+ {
shared_memory_object tmp(boost::move(moved));
this->swap(tmp);
- return *this;
+ return *this;
}
//!Swaps the shared_memory_objects. Does not throw
@@ -99,7 +104,7 @@ class shared_memory_object
//!Erases a shared memory object from the system.
//!Returns false on error. Never throws
static bool remove(const char *name);
-
+
//!Sets the size of the shared memory mapping
void truncate(offset_t length);
@@ -125,25 +130,26 @@ class shared_memory_object
//!Returns mapping handle. Never throws.
mapping_handle_t get_mapping_handle() const;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
//!Closes a previously opened file mapping. Never throws.
void priv_close();
- //!Closes a previously opened file mapping. Never throws.
+ //!Opens or creates a shared memory object.
bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm);
file_handle_t m_handle;
mode_t m_mode;
std::string m_filename;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline shared_memory_object::shared_memory_object()
: m_handle(file_handle_t(ipcdetail::invalid_file()))
+ , m_mode(read_only)
{}
inline shared_memory_object::~shared_memory_object()
@@ -157,10 +163,10 @@ inline bool shared_memory_object::get_size(offset_t &size) const
{ return ipcdetail::get_file_size((file_handle_t)m_handle, size); }
inline void shared_memory_object::swap(shared_memory_object &other)
-{
+{
std::swap(m_handle, other.m_handle);
std::swap(m_mode, other.m_mode);
- m_filename.swap(other.m_filename);
+ m_filename.swap(other.m_filename);
}
inline mapping_handle_t shared_memory_object::get_mapping_handle() const
@@ -178,7 +184,7 @@ inline bool shared_memory_object::priv_open_or_create
{
m_filename = filename;
std::string shmfile;
- ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, shmfile);
+ ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, shmfile);
//Set accesses
if (mode != read_write && mode != read_only){
@@ -219,7 +225,7 @@ inline bool shared_memory_object::remove(const char *filename)
try{
//Make sure a temporary path is created for shared memory
std::string shmfile;
- ipcdetail::tmp_filename(filename, shmfile);
+ ipcdetail::shared_filepath(filename, shmfile);
return ipcdetail::delete_file(shmfile.c_str());
}
catch(...){
@@ -283,7 +289,7 @@ inline bool shared_memory_object::priv_open_or_create
ipcdetail::add_leading_slash(filename, m_filename);
}
else{
- ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, m_filename);
+ ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, m_filename);
}
//Create new mapping
@@ -318,20 +324,26 @@ inline bool shared_memory_object::priv_open_or_create
break;
case ipcdetail::DoOpenOrCreate:
{
- oflag |= O_CREAT;
- //We need a loop to change permissions correctly using fchmod, since
- //with "O_CREAT only" shm_open we don't know if we've created or opened the file.
+ //We need a create/open loop to change permissions correctly using fchmod, since
+ //with "O_CREAT" only we don't know if we've created or opened the shm.
while(1){
- m_handle = shm_open(m_filename.c_str(), oflag, unix_perm);
+ //Try to create shared memory
+ m_handle = shm_open(m_filename.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm);
+ //If successful change real permissions
if(m_handle >= 0){
::fchmod(m_handle, unix_perm);
- break;
}
+ //If already exists, try to open
else if(errno == EEXIST){
- if((m_handle = shm_open(m_filename.c_str(), oflag, unix_perm)) >= 0 || errno != ENOENT){
- break;
+ m_handle = shm_open(m_filename.c_str(), oflag, unix_perm);
+ //If open fails and errno tells the file does not exist
+ //(shm was removed between creation and opening tries), just retry
+ if(m_handle < 0 && errno == ENOENT){
+ continue;
}
}
+ //Exit retries
+ break;
}
}
break;
@@ -343,7 +355,7 @@ inline bool shared_memory_object::priv_open_or_create
}
//Check for error
- if(m_handle == -1){
+ if(m_handle < 0){
error_info err = errno;
this->priv_close();
throw interprocess_exception(err);
@@ -357,7 +369,7 @@ inline bool shared_memory_object::priv_open_or_create
inline bool shared_memory_object::remove(const char *filename)
{
try{
- std::string file_str;
+ std::string filepath;
#if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
const bool add_leading_slash = false;
#elif defined(BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
@@ -366,12 +378,12 @@ inline bool shared_memory_object::remove(const char *filename)
const bool add_leading_slash = true;
#endif
if(add_leading_slash){
- ipcdetail::add_leading_slash(filename, file_str);
+ ipcdetail::add_leading_slash(filename, filepath);
}
else{
- ipcdetail::tmp_filename(filename, file_str);
+ ipcdetail::shared_filepath(filename, filepath);
}
- return 0 == shm_unlink(file_str.c_str());
+ return 0 == shm_unlink(filepath.c_str());
}
catch(...){
return false;
@@ -396,8 +408,6 @@ inline void shared_memory_object::priv_close()
#endif
-///@endcond
-
//!A class that stores the name of a shared memory
//!and calls shared_memory_object::remove(name) in its destructor
//!Useful to remove temporary shared memory objects in the presence
@@ -414,6 +424,8 @@ class remove_shared_memory_on_destroy
{ shared_memory_object::remove(m_name); }
};
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/smart_ptr/deleter.hpp b/boost/interprocess/smart_ptr/deleter.hpp
index 3a07ccd8f4..1a9e390018 100644
--- a/boost/interprocess/smart_ptr/deleter.hpp
+++ b/boost/interprocess/smart_ptr/deleter.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2007-2011.
+// (C) Copyright Ion Gaztanaga 2007-2012.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,7 +13,7 @@
#ifndef BOOST_INTERPROCESS_DELETER_HPP
#define BOOST_INTERPROCESS_DELETER_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp b/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp
index 9429613492..77ceda0c58 100644
--- a/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp
+++ b/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp
@@ -13,7 +13,7 @@
#ifndef BOOST_INTERPROCESS_BAD_WEAK_PTR_HPP_INCLUDED
#define BOOST_INTERPROCESS_BAD_WEAK_PTR_HPP_INCLUDED
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -36,7 +36,7 @@ class bad_weak_ptr
{ return "boost::interprocess::bad_weak_ptr"; }
};
-} // namespace interprocess
+} // namespace interprocess
} // namespace boost
#include <boost/interprocess/detail/config_end.hpp>
diff --git a/boost/interprocess/smart_ptr/detail/shared_count.hpp b/boost/interprocess/smart_ptr/detail/shared_count.hpp
index 7daaee6ea4..aed83eb2ab 100644
--- a/boost/interprocess/smart_ptr/detail/shared_count.hpp
+++ b/boost/interprocess/smart_ptr/detail/shared_count.hpp
@@ -4,7 +4,7 @@
//
// (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003
// (C) Copyright Peter Dimov 2004-2005
-// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -16,7 +16,7 @@
// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -116,7 +116,7 @@ class shared_count
}
~shared_count() // nothrow
- {
+ {
if(m_pi)
m_pi->release();
}
@@ -284,6 +284,7 @@ class weak_count
weak_count & operator= (weak_count const & r) // nothrow
{
+ m_px = r.m_px;
counted_impl_ptr tmp = r.m_pi;
if(tmp != 0) tmp->weak_add_ref();
if(m_pi != 0) m_pi->weak_release();
diff --git a/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp b/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp
index 24d96ee482..47743c1b91 100644
--- a/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp
+++ b/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2007-2011.
+// (C) Copyright Ion Gaztanaga 2007-2012.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -12,6 +12,10 @@
#ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
# include <boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp>
#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
diff --git a/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp b/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp
index edb39eeeb3..6ec1d56e59 100644
--- a/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp
+++ b/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp
@@ -3,13 +3,13 @@
// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#if defined(_MSC_VER)
# pragma once
#endif
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
-// Copyright 2007-2011 Ion Gaztanaga
+// Copyright 2007-2012 Ion Gaztanaga
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
diff --git a/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp b/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp
index 6a46bb75e6..3e01be5531 100644
--- a/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp
+++ b/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp
@@ -3,7 +3,7 @@
// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -63,7 +63,7 @@ struct scoped_ptr_dealloc_functor
{ if (ptr) priv_deallocate(ptr, alloc_version()); }
};
-
+
template<class A, class D>
class sp_counted_impl_pd
@@ -83,6 +83,8 @@ class sp_counted_impl_pd
portable_rebind_alloc
< const this_type >::type const_this_allocator;
typedef typename this_allocator::pointer this_pointer;
+ typedef typename boost::intrusive::
+ pointer_traits<this_pointer> this_pointer_traits;
sp_counted_impl_pd( sp_counted_impl_pd const & );
sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
@@ -115,14 +117,13 @@ class sp_counted_impl_pd
void destroy() // nothrow
{
- //Self destruction, so get a copy of the allocator
- //(in the future we could move it)
- this_allocator a_copy(*this);
+ //Self destruction, so move the allocator
+ this_allocator a_copy(::boost::move(static_cast<this_allocator&>(*this)));
BOOST_ASSERT(a_copy == *this);
- this_pointer this_ptr (this);
+ this_pointer this_ptr(this_pointer_traits::pointer_to(*this));
//Do it now!
scoped_ptr< this_type, scoped_ptr_dealloc_functor<this_allocator> >
- deleter(this_ptr, a_copy);
+ deleter_ptr(this_ptr, a_copy);
typedef typename this_allocator::value_type value_type;
ipcdetail::to_raw_pointer(this_ptr)->~value_type();
}
diff --git a/boost/interprocess/smart_ptr/enable_shared_from_this.hpp b/boost/interprocess/smart_ptr/enable_shared_from_this.hpp
index 9c8c7918f5..0ca3b0a390 100644
--- a/boost/interprocess/smart_ptr/enable_shared_from_this.hpp
+++ b/boost/interprocess/smart_ptr/enable_shared_from_this.hpp
@@ -3,7 +3,7 @@
// This file is the adaptation for Interprocess of boost/enable_shared_from_this.hpp
//
// (C) Copyright Peter Dimov 2002
-// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -14,6 +14,10 @@
#ifndef BOOST_INTERPROCESS_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
#define BOOST_INTERPROCESS_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -34,7 +38,7 @@ namespace interprocess{
template<class T, class A, class D>
class enable_shared_from_this
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
protected:
enable_shared_from_this()
{}
@@ -47,7 +51,7 @@ class enable_shared_from_this
~enable_shared_from_this()
{}
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
shared_ptr<T, A, D> shared_from_this()
@@ -64,10 +68,10 @@ class enable_shared_from_this
return p;
}
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef T element_type;
mutable weak_ptr<element_type, A, D> _internal_weak_this;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
} // namespace interprocess
diff --git a/boost/interprocess/smart_ptr/intrusive_ptr.hpp b/boost/interprocess/smart_ptr/intrusive_ptr.hpp
index f6d5c8b77c..ff66512251 100644
--- a/boost/interprocess/smart_ptr/intrusive_ptr.hpp
+++ b/boost/interprocess/smart_ptr/intrusive_ptr.hpp
@@ -3,7 +3,7 @@
// This file is the adaptation for Interprocess of boost/intrusive_ptr.hpp
//
// (C) Copyright Peter Dimov 2001, 2002
-// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -14,6 +14,10 @@
#ifndef BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED
#define BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
//!\file
//!Describes an intrusive ownership pointer.
@@ -56,12 +60,12 @@ class intrusive_ptr
//!Provides the type of the stored pointer.
typedef T element_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef VoidPointer VP;
typedef intrusive_ptr this_type;
typedef pointer this_type::*unspecified_bool_type;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor. Initializes internal pointer to 0.
@@ -125,7 +129,7 @@ class intrusive_ptr
this_type(rhs).swap(*this);
return *this;
}
-
+
//!Returns a reference to the internal pointer.
//!Does not throw
pointer &get()
@@ -166,10 +170,10 @@ class intrusive_ptr
void swap(intrusive_ptr & rhs)
{ ipcdetail::do_swap(m_ptr, rhs.m_ptr); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
pointer m_ptr;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!Returns a.get() == b.get().
@@ -219,9 +223,9 @@ bool operator!=(const typename intrusive_ptr<T, VP>::pointer &a,
template<class T, class VP> inline
bool operator<(intrusive_ptr<T, VP> const & a,
intrusive_ptr<T, VP> const & b)
-{
+{
return std::less<typename intrusive_ptr<T, VP>::pointer>()
- (a.get(), b.get());
+ (a.get(), b.get());
}
//!Exchanges the contents of the two intrusive_ptrs.
@@ -277,7 +281,7 @@ inline boost::interprocess::intrusive_ptr<T, VP>reinterpret_pointer_cast
} // namespace interprocess
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if defined(_MSC_VER) && (_MSC_VER < 1400)
//!Returns p.get().
@@ -287,7 +291,7 @@ inline T *to_raw_pointer(boost::interprocess::intrusive_ptr<T, VP> p)
{ return p.get(); }
#endif
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} // namespace boost
diff --git a/boost/interprocess/smart_ptr/scoped_ptr.hpp b/boost/interprocess/smart_ptr/scoped_ptr.hpp
index a3755d3592..e628608c9a 100644
--- a/boost/interprocess/smart_ptr/scoped_ptr.hpp
+++ b/boost/interprocess/smart_ptr/scoped_ptr.hpp
@@ -4,7 +4,7 @@
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// (C) Copyright Peter Dimov 2001, 2002
-// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -15,6 +15,10 @@
#ifndef BOOST_INTERPROCESS_SCOPED_PTR_HPP_INCLUDED
#define BOOST_INTERPROCESS_SCOPED_PTR_HPP_INCLUDED
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/pointer_type.hpp>
@@ -40,13 +44,13 @@ template<class T, class Deleter>
class scoped_ptr
: private Deleter
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
scoped_ptr(scoped_ptr const &);
scoped_ptr & operator=(scoped_ptr const &);
typedef scoped_ptr<T, Deleter> this_type;
typedef typename ipcdetail::add_reference<T>::type reference;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
@@ -127,10 +131,10 @@ class scoped_ptr
void swap(scoped_ptr & b) // never throws
{ ipcdetail::do_swap<Deleter>(*this, b); ipcdetail::do_swap(m_ptr, b.m_ptr); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
pointer m_ptr;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!Exchanges the internal pointer and deleter with other scoped_ptr
@@ -147,7 +151,7 @@ typename scoped_ptr<T, D>::pointer to_raw_pointer(scoped_ptr<T, D> const & p)
} // namespace interprocess
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if defined(_MSC_VER) && (_MSC_VER < 1400)
template<class T, class D> inline
@@ -155,7 +159,7 @@ T *to_raw_pointer(boost::interprocess::scoped_ptr<T, D> const & p)
{ return p.get(); }
#endif
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} // namespace boost
diff --git a/boost/interprocess/smart_ptr/shared_ptr.hpp b/boost/interprocess/smart_ptr/shared_ptr.hpp
index 5ede547a3f..fdf7235727 100644
--- a/boost/interprocess/smart_ptr/shared_ptr.hpp
+++ b/boost/interprocess/smart_ptr/shared_ptr.hpp
@@ -4,7 +4,7 @@
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// (C) Copyright Peter Dimov 2001, 2002, 2003
-// (C) Copyright Ion Gaztanaga 2006-2011.
+// (C) Copyright Ion Gaztanaga 2006-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -16,6 +16,10 @@
#ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED
#define BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -24,7 +28,7 @@
#include <boost/assert.hpp>
#include <boost/interprocess/smart_ptr/detail/shared_count.hpp>
#include <boost/interprocess/detail/mpl.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/smart_ptr/deleter.hpp>
@@ -52,7 +56,7 @@ inline void sp_enable_shared_from_this
(shared_count<T, VoidAllocator, Deleter> const & pn
,enable_shared_from_this<T, VoidAllocator, Deleter> *pe
,T *ptr)
-
+
{
(void)ptr;
if(pe != 0){
@@ -88,10 +92,10 @@ inline void sp_enable_shared_from_this(shared_count<T, VoidAllocator, Deleter> c
template<class T, class VoidAllocator, class Deleter>
class shared_ptr
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef shared_ptr<T, VoidAllocator, Deleter> this_type;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
@@ -125,7 +129,7 @@ class shared_ptr
//!Requirements: Deleter and A's copy constructor must not throw.
explicit shared_ptr(const pointer&p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter())
: m_pn(p, a, d)
- {
+ {
//Check that the pointer passed is of the same type that
//the pointer the allocator defines or it's a raw pointer
typedef typename boost::intrusive::
@@ -171,7 +175,7 @@ class shared_ptr
: m_pn()
{ this->swap(other); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template<class Y>
shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::static_cast_tag)
: m_pn( pointer(static_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
@@ -193,7 +197,7 @@ class shared_ptr
m_pn = ipcdetail::shared_count<T, VoidAllocator, Deleter>();
}
}
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Equivalent to shared_ptr(r).swap(*this).
//!Never throws
@@ -223,15 +227,15 @@ class shared_ptr
//!This is equivalent to:
//!this_type().swap(*this);
void reset()
- {
- this_type().swap(*this);
+ {
+ this_type().swap(*this);
}
//!This is equivalent to:
//!this_type(p, a, d).swap(*this);
template<class Pointer>
void reset(const Pointer &p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter())
- {
+ {
//Check that the pointer passed is of the same type that
//the pointer the allocator defines or it's a raw pointer
typedef typename boost::intrusive::
@@ -239,7 +243,7 @@ class shared_ptr
rebind_pointer<T>::type ParameterPointer;
BOOST_STATIC_ASSERT((ipcdetail::is_same<pointer, ParameterPointer>::value) ||
(ipcdetail::is_pointer<Pointer>::value));
- this_type(p, a, d).swap(*this);
+ this_type(p, a, d).swap(*this);
}
template<class Y>
@@ -263,14 +267,14 @@ class shared_ptr
pointer get() const // never throws
{ return m_pn.to_raw_pointer(); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
// implicit conversion to "bool"
void unspecified_bool_type_func() const {}
typedef void (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const // never throws
{ return !m_pn.to_raw_pointer() ? 0 : &this_type::unspecified_bool_type_func; }
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Not operator.
//!Returns true if this->get() != 0, false otherwise
@@ -295,7 +299,7 @@ class shared_ptr
void swap(shared_ptr<T, VoidAllocator, Deleter> & other) // never throws
{ m_pn.swap(other.m_pn); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template<class T2, class A2, class Deleter2>
bool _internal_less(shared_ptr<T2, A2, Deleter2> const & rhs) const
@@ -313,7 +317,7 @@ class shared_ptr
template<class T2, class A2, class Deleter2> friend class weak_ptr;
ipcdetail::shared_count<T, VoidAllocator, Deleter> m_pn; // reference counter
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
}; // shared_ptr
template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
@@ -404,7 +408,7 @@ inline typename managed_shared_ptr<T, ManagedMemory>::type
} // namespace interprocess
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if defined(_MSC_VER) && (_MSC_VER < 1400)
// to_raw_pointer() enables boost::mem_fn to recognize shared_ptr
@@ -413,7 +417,7 @@ T * to_raw_pointer(boost::interprocess::shared_ptr<T, VoidAllocator, Deleter> co
{ return p.get(); }
#endif
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} // namespace boost
diff --git a/boost/interprocess/smart_ptr/unique_ptr.hpp b/boost/interprocess/smart_ptr/unique_ptr.hpp
index 89cdb1e6e2..9e51c93508 100644
--- a/boost/interprocess/smart_ptr/unique_ptr.hpp
+++ b/boost/interprocess/smart_ptr/unique_ptr.hpp
@@ -1,11 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
-// I, Howard Hinnant, hereby place this code in the public domain.
-//////////////////////////////////////////////////////////////////////////////
-//
-// This file is the adaptation for Interprocess of
-// Howard Hinnant's unique_ptr emulation code.
//
-// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2006-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -16,509 +11,22 @@
#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED
#define BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <boost/assert.hpp>
-#include <boost/interprocess/detail/utilities.hpp>
-#include <boost/interprocess/detail/pointer_type.hpp>
-#include <boost/move/move.hpp>
-#include <boost/compressed_pair.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/interprocess/detail/mpl.hpp>
-#include <boost/interprocess/detail/type_traits.hpp>
-#include <boost/interprocess/smart_ptr/deleter.hpp>
-#include <cstddef>
+#include <boost/move/unique_ptr.hpp>
//!\file
-//!Describes the smart pointer unique_ptr
+//!This header provides utilities to define a unique_ptr that plays nicely with managed segments.
namespace boost{
namespace interprocess{
-/// @cond
-template <class T, class D> class unique_ptr;
-
-namespace ipcdetail {
-
-template <class T> struct unique_ptr_error;
-
-template <class T, class D>
-struct unique_ptr_error<const unique_ptr<T, D> >
-{
- typedef unique_ptr<T, D> type;
-};
-
-} //namespace ipcdetail {
-/// @endcond
-
-//!Template unique_ptr stores a pointer to an object and deletes that object
-//!using the associated deleter when it is itself destroyed (such as when
-//!leaving block scope.
-//!
-//!The unique_ptr provides a semantics of strict ownership. A unique_ptr owns the
-//!object it holds a pointer to.
-//!
-//!A unique_ptr is not CopyConstructible, nor CopyAssignable, however it is
-//!MoveConstructible and Move-Assignable.
-//!
-//!The uses of unique_ptr include providing exception safety for dynamically
-//!allocated memory, passing ownership of dynamically allocated memory to a
-//!function, and returning dynamically allocated memory from a function
-//!
-//!A client-supplied template argument D must be a
-//!function pointer or functor for which, given a value d of type D and a pointer
-//!ptr to a type T*, the expression d(ptr) is
-//!valid and has the effect of deallocating the pointer as appropriate for that
-//!deleter. D may also be an lvalue-reference to a deleter.
-//!
-//!If the deleter D maintains state, it is intended that this state stay with
-//!the associated pointer as ownership is transferred
-//!from unique_ptr to unique_ptr. The deleter state need never be copied,
-//!only moved or swapped as pointer ownership
-//!is moved around. That is, the deleter need only be MoveConstructible,
-//!MoveAssignable, and Swappable, and need not be CopyConstructible
-//!(unless copied into the unique_ptr) nor CopyAssignable.
-template <class T, class D>
-class unique_ptr
-{
- /// @cond
- struct nat {int for_bool_;};
- typedef typename ipcdetail::add_reference<D>::type deleter_reference;
- typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference;
- /// @endcond
-
- public:
-
- typedef T element_type;
- typedef D deleter_type;
- typedef typename ipcdetail::pointer_type<T, D>::type pointer;
-
- //!Requires: D must be default constructible, and that construction must not
- //!throw an exception. D must not be a reference type.
- //!
- //!Effects: Constructs a unique_ptr which owns nothing.
- //!
- //!Postconditions: get() == 0. get_deleter() returns a reference to a
- //!default constructed deleter D.
- //!
- //!Throws: nothing.
- unique_ptr()
- : ptr_(pointer(0))
- {}
-
- //!Requires: The expression D()(p) must be well formed. The default constructor
- //!of D must not throw an exception.
- //!
- //!D must not be a reference type.
- //!
- //!Effects: Constructs a unique_ptr which owns p.
- //!
- //!Postconditions: get() == p. get_deleter() returns a reference to a default constructed deleter D.
- //!
- //!Throws: nothing.
- explicit unique_ptr(pointer p)
- : ptr_(p)
- {}
-
- //!Requires: The expression d(p) must be well formed.
- //!
- //!Postconditions: get() == p. get_deleter() returns a reference to the
- //!internally stored deleter. If D is a
- //!reference type then get_deleter() returns a reference to the lvalue d.
- //!
- //!Throws: nothing.
- unique_ptr(pointer p
- ,typename ipcdetail::if_<ipcdetail::is_reference<D>
- ,D
- ,typename ipcdetail::add_reference<const D>::type>::type d)
- : ptr_(p, d)
- {}
-
- //!Requires: If the deleter is not a reference type, construction of the
- //!deleter D from an lvalue D must not throw an exception.
- //!
- //!Effects: Constructs a unique_ptr which owns the pointer which u owns
- //!(if any). If the deleter is not a reference type, it is move constructed
- //!from u's deleter, otherwise the reference is copy constructed from u's deleter.
- //!
- //!After the construction, u no longer owns a pointer.
- //![ Note: The deleter constructor can be implemented with
- //! boost::forward<D>. -end note ]
- //!
- //!Postconditions: get() == value u.get() had before the construction.
- //!get_deleter() returns a reference to the internally stored deleter which
- //!was constructed from u.get_deleter(). If D is a reference type then get_-
- //!deleter() and u.get_deleter() both reference the same lvalue deleter.
- //!
- //!Throws: nothing.
- unique_ptr(BOOST_RV_REF(unique_ptr) u)
- : ptr_(u.release(), boost::forward<D>(u.get_deleter()))
- {}
-
- //!Requires: If D is not a reference type, construction of the deleter
- //!D from an rvalue of type E must be well formed
- //!and not throw an exception. If D is a reference type, then E must be
- //!the same type as D (diagnostic required). unique_ptr<U, E>::pointer
- //!must be implicitly convertible to pointer.
- //!
- //!Effects: Constructs a unique_ptr which owns the pointer which u owns
- //!(if any). If the deleter is not a reference
- //!type, it is move constructed from u's deleter, otherwise the reference
- //!is copy constructed from u's deleter.
- //!
- //!After the construction, u no longer owns a pointer.
- //!
- //!postconditions get() == value u.get() had before the construction,
- //!modulo any required offset adjustments
- //!resulting from the cast from U* to T*. get_deleter() returns a reference to the internally stored deleter which
- //!was constructed from u.get_deleter().
- //!
- //!Throws: nothing.
- template <class U, class E>
- unique_ptr(BOOST_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u,
- typename ipcdetail::enable_if_c<
- ipcdetail::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
- ipcdetail::is_convertible<E, D>::value &&
- (
- !ipcdetail::is_reference<D>::value ||
- ipcdetail::is_same<D, E>::value
- )
- ,
- nat
- >::type = nat())
- : ptr_(const_cast<unique_ptr<U,E>&>(u).release(), boost::move<D>(u.get_deleter()))
- {}
-
- //!Effects: If get() == 0 there are no effects. Otherwise get_deleter()(get()).
- //!
- //!Throws: nothing.
- ~unique_ptr()
- { reset(); }
-
- // assignment
-
- //!Requires: Assignment of the deleter D from an rvalue D must not throw an exception.
- //!
- //!Effects: reset(u.release()) followed by a move assignment from u's deleter to
- //!this deleter.
- //!
- //!Postconditions: This unique_ptr now owns the pointer which u owned, and u no
- //!longer owns it.
- //!
- //!Returns: *this.
- //!
- //!Throws: nothing.
- unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u)
- {
- reset(u.release());
- ptr_.second() = boost::move(u.get_deleter());
- return *this;
- }
-
- //!Requires: Assignment of the deleter D from an rvalue D must not
- //!throw an exception. U* must be implicitly convertible to T*.
- //!
- //!Effects: reset(u.release()) followed by a move assignment from
- //!u's deleter to this deleter. If either D or E is
- //!a reference type, then the referenced lvalue deleter participates
- //!in the move assignment.
- //!
- //!Postconditions: This unique_ptr now owns the pointer which u owned,
- //!and u no longer owns it.
- //!
- //!Returns: *this.
- //!
- //!Throws: nothing.
- template <class U, class E>
- unique_ptr& operator=(BOOST_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u)
- {
- reset(u.release());
- ptr_.second() = boost::move(u.get_deleter());
- return *this;
- }
-
- //!Assigns from the literal 0 or NULL.
- //!
- //!Effects: reset().
- //!
- //!Postcondition: get() == 0
- //!
- //!Returns: *this.
- //!
- //!Throws: nothing.
- unique_ptr& operator=(int nat::*)
- {
- reset();
- return *this;
- }
-
- //!Requires: get() != 0.
- //!Returns: *get().
- //!Throws: nothing.
- typename ipcdetail::add_reference<T>::type operator*() const
- { return *ptr_.first(); }
-
- //!Requires: get() != 0.
- //!Returns: get().
- //!Throws: nothing.
- pointer operator->() const
- { return ptr_.first(); }
-
- //!Returns: The stored pointer.
- //!Throws: nothing.
- pointer get() const
- { return ptr_.first(); }
-
- //!Returns: A reference to the stored deleter.
- //!
- //!Throws: nothing.
- deleter_reference get_deleter()
- { return ptr_.second(); }
-
- //!Returns: A const reference to the stored deleter.
- //!
- //!Throws: nothing.
- deleter_const_reference get_deleter() const
- { return ptr_.second(); }
-
- //!Returns: An unspecified value that, when used in boolean
- //!contexts, is equivalent to get() != 0.
- //!
- //!Throws: nothing.
- operator int nat::*() const
- { return ptr_.first() ? &nat::for_bool_ : 0; }
-
- //!Postcondition: get() == 0.
- //!
- //!Returns: The value get() had at the start of the call to release.
- //!
- //!Throws: nothing.
- pointer release()
- {
- pointer tmp = ptr_.first();
- ptr_.first() = 0;
- return tmp;
- }
-
- //!Effects: If p == get() there are no effects. Otherwise get_deleter()(get()).
- //!
- //!Postconditions: get() == p.
- //!
- //!Throws: nothing.
- void reset(pointer p = 0)
- {
- if (ptr_.first() != p){
- if (ptr_.first())
- ptr_.second()(ptr_.first());
- ptr_.first() = p;
- }
- }
-
- //!Requires: The deleter D is Swappable and will not throw an exception under swap.
- //!
- //!Effects: The stored pointers of this and u are exchanged.
- //! The stored deleters are swapped (unqualified).
- //!Throws: nothing.
- void swap(unique_ptr& u)
- { ptr_.swap(u.ptr_); }
-
- /// @cond
- private:
- boost::compressed_pair<pointer, D> ptr_;
- BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr)
- template <class U, class E> unique_ptr(unique_ptr<U, E>&);
- template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0);
-
- template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&);
- template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&);
- /// @endcond
-};
-/*
-template <class T, class D>
-class unique_ptr<T[], D>
-{
- struct nat {int for_bool_;};
- typedef typename ipcdetail::add_reference<D>::type deleter_reference;
- typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference;
-public:
- typedef T element_type;
- typedef D deleter_type;
- typedef typename ipcdetail::pointer_type<T, D>::type pointer;
-
- // constructors
- unique_ptr() : ptr_(pointer()) {}
- explicit unique_ptr(pointer p) : ptr_(p) {}
- unique_ptr(pointer p, typename if_<
- boost::is_reference<D>,
- D,
- typename ipcdetail::add_reference<const D>::type>::type d)
- : ptr_(p, d) {}
- unique_ptr(const unique_ptr& u)
- : ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
-
- // destructor
- ~unique_ptr() {reset();}
-
- // assignment
- unique_ptr& operator=(const unique_ptr& cu)
- {
- unique_ptr& u = const_cast<unique_ptr&>(cu);
- reset(u.release());
- ptr_.second() = u.get_deleter();
- return *this;
- }
- unique_ptr& operator=(int nat::*)
- {
- reset();
- return *this;
- }
-
- // observers
- typename ipcdetail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
- pointer get() const {return ptr_.first();}
- deleter_reference get_deleter() {return ptr_.second();}
- deleter_const_reference get_deleter() const {return ptr_.second();}
- operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
-
- // modifiers
- pointer release()
- {
- pointer tmp = ptr_.first();
- ptr_.first() = 0;
- return tmp;
- }
- void reset(pointer p = 0)
- {
- if (ptr_.first() != p)
- {
- if (ptr_.first())
- ptr_.second()(ptr_.first());
- ptr_.first() = p;
- }
- }
- void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
-private:
- boost::compressed_pair<pointer, D> ptr_;
-
- template <class U, class E> unique_ptr(U p, E,
- typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
- template <class U> explicit unique_ptr(U,
- typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
-
- unique_ptr(unique_ptr&);
- template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0);
-
- unique_ptr& operator=(unique_ptr&);
- template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&);
-};
-
-template <class T, class D, std::size_t N>
-class unique_ptr<T[N], D>
-{
- struct nat {int for_bool_;};
- typedef typename ipcdetail::add_reference<D>::type deleter_reference;
- typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference;
-public:
- typedef T element_type;
- typedef D deleter_type;
- typedef typename ipcdetail::pointer_type<T, D>::type pointer;
- static const std::size_t size = N;
-
- // constructors
- unique_ptr() : ptr_(0) {}
- explicit unique_ptr(pointer p) : ptr_(p) {}
- unique_ptr(pointer p, typename if_<
- boost::is_reference<D>,
- D,
- typename ipcdetail::add_reference<const D>::type>::type d)
- : ptr_(p, d) {}
- unique_ptr(const unique_ptr& u)
- : ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
-
- // destructor
- ~unique_ptr() {reset();}
-
- // assignment
- unique_ptr& operator=(const unique_ptr& cu)
- {
- unique_ptr& u = const_cast<unique_ptr&>(cu);
- reset(u.release());
- ptr_.second() = u.get_deleter();
- return *this;
- }
- unique_ptr& operator=(int nat::*)
- {
- reset();
- return *this;
- }
-
- // observers
- typename ipcdetail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
- pointer get() const {return ptr_.first();}
- deleter_reference get_deleter() {return ptr_.second();}
- deleter_const_reference get_deleter() const {return ptr_.second();}
- operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
-
- // modifiers
- pointer release()
- {
- pointer tmp = ptr_.first();
- ptr_.first() = 0;
- return tmp;
- }
- void reset(pointer p = 0)
- {
- if (ptr_.first() != p)
- {
- if (ptr_.first())
- ptr_.second()(ptr_.first(), N);
- ptr_.first() = p;
- }
- }
- void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
-private:
- boost::compressed_pair<pointer, D> ptr_;
-
- template <class U, class E> unique_ptr(U p, E,
- typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
- template <class U> explicit unique_ptr(U,
- typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
-
- unique_ptr(unique_ptr&);
- template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0);
-
- unique_ptr& operator=(unique_ptr&);
- template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&);
-};
-*/
-template <class T, class D> inline
-void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y)
-{ x.swap(y); }
-
-template <class T1, class D1, class T2, class D2> inline
-bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
-{ return x.get() == y.get(); }
-
-template <class T1, class D1, class T2, class D2> inline
-bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
-{ return x.get() != y.get(); }
-
-template <class T1, class D1, class T2, class D2> inline
-bool operator <(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
-{ return x.get() < y.get(); }
-
-template <class T1, class D1, class T2, class D2> inline
-bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
-{ return x.get() <= y.get(); }
-
-template <class T1, class D1, class T2, class D2> inline
-bool operator >(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
-{ return x.get() > y.get(); }
-
-template <class T1, class D1, class T2, class D2> inline
-bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
-{ return x.get() >= y.get(); }
-
+//For backwards compatibility
+using ::boost::movelib::unique_ptr;
//!Returns the type of a unique pointer
//!of type T with boost::interprocess::deleter deleter
@@ -526,7 +34,7 @@ bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
template<class T, class ManagedMemory>
struct managed_unique_ptr
{
- typedef unique_ptr
+ typedef boost::movelib::unique_ptr
< T
, typename ManagedMemory::template deleter<T>::type
> type;
diff --git a/boost/interprocess/smart_ptr/weak_ptr.hpp b/boost/interprocess/smart_ptr/weak_ptr.hpp
index 5202ede91c..e4c47cb253 100644
--- a/boost/interprocess/smart_ptr/weak_ptr.hpp
+++ b/boost/interprocess/smart_ptr/weak_ptr.hpp
@@ -3,7 +3,7 @@
// This file is the adaptation for Interprocess of boost/weak_ptr.hpp
//
// (C) Copyright Peter Dimov 2001, 2002, 2003
-// (C) Copyright Ion Gaztanaga 2006-2011.
+// (C) Copyright Ion Gaztanaga 2006-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -15,6 +15,10 @@
#ifndef BOOST_INTERPROCESS_WEAK_PTR_HPP_INCLUDED
#define BOOST_INTERPROCESS_WEAK_PTR_HPP_INCLUDED
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -50,7 +54,7 @@ namespace interprocess{
template<class T, class A, class D>
class weak_ptr
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
// Borland 5.5.1 specific workarounds
typedef weak_ptr<T, A, D> this_type;
@@ -61,7 +65,7 @@ class weak_ptr
<T>::type reference;
typedef typename ipcdetail::add_reference
<T>::type const_reference;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
typedef T element_type;
@@ -99,7 +103,7 @@ class weak_ptr
template<class Y>
weak_ptr(weak_ptr<Y, A, D> const & r)
: m_pn(r.m_pn) // never throws
- {
+ {
//Construct a temporary shared_ptr so that nobody
//can destroy the value while constructing this
const shared_ptr<T, A, D> &ref = r.lock();
@@ -126,7 +130,7 @@ class weak_ptr
//!implied guarantees) via different means, without creating a temporary.
template<class Y>
weak_ptr & operator=(weak_ptr<Y, A, D> const & r) // never throws
- {
+ {
//Construct a temporary shared_ptr so that nobody
//can destroy the value while constructing this
const shared_ptr<T, A, D> &ref = r.lock();
@@ -174,7 +178,7 @@ class weak_ptr
//!testing purposes, not for production code.
long use_count() const // never throws
{ return m_pn.use_count(); }
-
+
//!Returns: Returns: use_count() == 0.
//!
//!Throws: nothing.
@@ -195,11 +199,11 @@ class weak_ptr
void swap(this_type & other) // never throws
{ ipcdetail::do_swap(m_pn, other.m_pn); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template<class T2, class A2, class D2>
bool _internal_less(weak_ptr<T2, A2, D2> const & rhs) const
{ return m_pn < rhs.m_pn; }
-
+
template<class Y>
void _internal_assign(const ipcdetail::shared_count<Y, A, D> & pn2)
{
@@ -213,7 +217,7 @@ class weak_ptr
template<class T2, class A2, class D2> friend class weak_ptr;
ipcdetail::weak_count<T, A, D> m_pn; // reference counter
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
}; // weak_ptr
template<class T, class A, class D, class U, class A2, class D2> inline
diff --git a/boost/interprocess/streams/bufferstream.hpp b/boost/interprocess/streams/bufferstream.hpp
index 3ae9f5e2dc..cb3e637939 100644
--- a/boost/interprocess/streams/bufferstream.hpp
+++ b/boost/interprocess/streams/bufferstream.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -8,7 +8,7 @@
//
//////////////////////////////////////////////////////////////////////////////
//
-// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005.
+// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012.
// Changed internal SGI string to a buffer. Added efficient
// internal buffer get/set/swap functions, so that we can obtain/establish the
// internal buffer without any reallocation or copy. Kill those temporaries!
@@ -35,6 +35,10 @@
#ifndef BOOST_INTERPROCESS_BUFFERSTREAM_HPP
#define BOOST_INTERPROCESS_BUFFERSTREAM_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -42,7 +46,7 @@
#include <ios>
#include <istream>
#include <ostream>
-#include <string> // char traits
+#include <string> // char traits
#include <cstddef> // ptrdiff_t
#include <boost/assert.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
@@ -74,10 +78,10 @@ class basic_bufferbuf
//!Constructor. Assigns formatting buffer.
//!Does not throw.
- explicit basic_bufferbuf(CharT *buffer, std::size_t length,
+ explicit basic_bufferbuf(CharT *buf, std::size_t length,
std::ios_base::openmode mode
= std::ios_base::in | std::ios_base::out)
- : base_t(), m_mode(mode), m_buffer(buffer), m_length(length)
+ : base_t(), m_mode(mode), m_buffer(buf), m_length(length)
{ this->set_pointers(); }
virtual ~basic_bufferbuf(){}
@@ -90,10 +94,10 @@ class basic_bufferbuf
//!Sets the underlying buffer to a new value
//!Does not throw.
- void buffer(CharT *buffer, std::size_t length)
- { m_buffer = buffer; m_length = length; this->set_pointers(); }
+ void buffer(CharT *buf, std::size_t length)
+ { m_buffer = buf; m_length = length; this->set_pointers(); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
void set_pointers()
{
@@ -177,7 +181,7 @@ class basic_bufferbuf
{
bool in = false;
bool out = false;
-
+
const std::ios_base::openmode inout =
std::ios_base::in | std::ios_base::out;
@@ -245,14 +249,17 @@ class basic_bufferbuf
std::ios_base::openmode m_mode;
CharT * m_buffer;
std::size_t m_length;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!A basic_istream class that uses a fixed size character buffer
//!as its formatting buffer.
template <class CharT, class CharTraits>
-class basic_ibufferstream
- : public std::basic_istream<CharT, CharTraits>
+class basic_ibufferstream :
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ private basic_bufferbuf<CharT, CharTraits>,
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ public std::basic_istream<CharT, CharTraits>
{
public: // Typedefs
typedef typename std::basic_ios
@@ -262,24 +269,40 @@ class basic_ibufferstream
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
- typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
- typedef std::basic_istream<char_type, CharTraits> base_t;
+ typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t;
+ typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
+ typedef std::basic_istream<char_type, CharTraits> base_t;
+ bufferbuf_t & get_buf() { return *this; }
+ const bufferbuf_t & get_buf() const{ return *this; }
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor.
//!Does not throw.
basic_ibufferstream(std::ios_base::openmode mode = std::ios_base::in)
- : basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::in)
- { basic_ios_t::init(&m_buf); }
+ : //basic_ios_t() is called first (lefting it uninitialized) as it's a
+ //virtual base of basic_istream. The class will be initialized when
+ //basic_istream is constructed calling basic_ios_t::init().
+ //As bufferbuf_t's constructor does not throw there is no risk of
+ //calling the basic_ios_t's destructor without calling basic_ios_t::init()
+ bufferbuf_t(mode | std::ios_base::in)
+ , base_t(&get_buf())
+ {}
//!Constructor. Assigns formatting buffer.
//!Does not throw.
- basic_ibufferstream(const CharT *buffer, std::size_t length,
- std::ios_base::openmode mode = std::ios_base::in)
- : basic_ios_t(), base_t(0),
- m_buf(const_cast<CharT*>(buffer), length, mode | std::ios_base::in)
- { basic_ios_t::init(&m_buf); }
+ basic_ibufferstream(const CharT *buf, std::size_t length,
+ std::ios_base::openmode mode = std::ios_base::in)
+ : //basic_ios_t() is called first (lefting it uninitialized) as it's a
+ //virtual base of basic_istream. The class will be initialized when
+ //basic_istream is constructed calling basic_ios_t::init().
+ //As bufferbuf_t's constructor does not throw there is no risk of
+ //calling the basic_ios_t's destructor without calling basic_ios_t::init()
+ bufferbuf_t(const_cast<CharT*>(buf), length, mode | std::ios_base::in)
+ , base_t(&get_buf())
+ {}
~basic_ibufferstream(){};
@@ -287,29 +310,27 @@ class basic_ibufferstream
//!Returns the address of the stored
//!stream buffer.
basic_bufferbuf<CharT, CharTraits>* rdbuf() const
- { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
+ { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); }
//!Returns the pointer and size of the internal buffer.
//!Does not throw.
std::pair<const CharT *, std::size_t> buffer() const
- { return m_buf.buffer(); }
+ { return get_buf().buffer(); }
//!Sets the underlying buffer to a new value. Resets
//!stream position. Does not throw.
- void buffer(const CharT *buffer, std::size_t length)
- { m_buf.buffer(const_cast<CharT*>(buffer), length); }
-
- /// @cond
- private:
- basic_bufferbuf<CharT, CharTraits> m_buf;
- /// @endcond
+ void buffer(const CharT *buf, std::size_t length)
+ { get_buf().buffer(const_cast<CharT*>(buf), length); }
};
//!A basic_ostream class that uses a fixed size character buffer
//!as its formatting buffer.
template <class CharT, class CharTraits>
-class basic_obufferstream
- : public std::basic_ostream<CharT, CharTraits>
+class basic_obufferstream :
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ private basic_bufferbuf<CharT, CharTraits>,
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ public std::basic_ostream<CharT, CharTraits>
{
public:
typedef typename std::basic_ios
@@ -319,25 +340,40 @@ class basic_obufferstream
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
+ typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t;
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
typedef std::basic_ostream<char_type, CharTraits> base_t;
- /// @endcond
+ bufferbuf_t & get_buf() { return *this; }
+ const bufferbuf_t & get_buf() const{ return *this; }
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
public:
//!Constructor.
//!Does not throw.
basic_obufferstream(std::ios_base::openmode mode = std::ios_base::out)
- : basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::out)
- { basic_ios_t::init(&m_buf); }
+ : //basic_ios_t() is called first (lefting it uninitialized) as it's a
+ //virtual base of basic_istream. The class will be initialized when
+ //basic_istream is constructed calling basic_ios_t::init().
+ //As bufferbuf_t's constructor does not throw there is no risk of
+ //calling the basic_ios_t's destructor without calling basic_ios_t::init()
+ bufferbuf_t(mode | std::ios_base::out)
+ , base_t(&get_buf())
+ {}
//!Constructor. Assigns formatting buffer.
//!Does not throw.
- basic_obufferstream(CharT *buffer, std::size_t length,
+ basic_obufferstream(CharT *buf, std::size_t length,
std::ios_base::openmode mode = std::ios_base::out)
- : basic_ios_t(), base_t(0),
- m_buf(buffer, length, mode | std::ios_base::out)
- { basic_ios_t::init(&m_buf); }
+ : //basic_ios_t() is called first (lefting it uninitialized) as it's a
+ //virtual base of basic_istream. The class will be initialized when
+ //basic_istream is constructed calling basic_ios_t::init().
+ //As bufferbuf_t's constructor does not throw there is no risk of
+ //calling the basic_ios_t's destructor without calling basic_ios_t::init()
+ bufferbuf_t(buf, length, mode | std::ios_base::out)
+ , base_t(&get_buf())
+ {}
~basic_obufferstream(){}
@@ -345,31 +381,28 @@ class basic_obufferstream
//!Returns the address of the stored
//!stream buffer.
basic_bufferbuf<CharT, CharTraits>* rdbuf() const
- { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
+ { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); }
//!Returns the pointer and size of the internal buffer.
//!Does not throw.
std::pair<CharT *, std::size_t> buffer() const
- { return m_buf.buffer(); }
+ { return get_buf().buffer(); }
//!Sets the underlying buffer to a new value. Resets
//!stream position. Does not throw.
- void buffer(CharT *buffer, std::size_t length)
- { m_buf.buffer(buffer, length); }
-
- /// @cond
- private:
- basic_bufferbuf<CharT, CharTraits> m_buf;
- /// @endcond
+ void buffer(CharT *buf, std::size_t length)
+ { get_buf().buffer(buf, length); }
};
//!A basic_iostream class that uses a fixed size character buffer
//!as its formatting buffer.
template <class CharT, class CharTraits>
-class basic_bufferstream
- : public std::basic_iostream<CharT, CharTraits>
-
+class basic_bufferstream :
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ private basic_bufferbuf<CharT, CharTraits>,
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ public std::basic_iostream<CharT, CharTraits>
{
public: // Typedefs
typedef typename std::basic_ios
@@ -379,27 +412,42 @@ class basic_bufferstream
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
- typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
- typedef std::basic_iostream<char_type, CharTraits> base_t;
- /// @endcond
+ typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t;
+ typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
+ typedef std::basic_iostream<char_type, CharTraits> base_t;
+ bufferbuf_t & get_buf() { return *this; }
+ const bufferbuf_t & get_buf() const{ return *this; }
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor.
//!Does not throw.
basic_bufferstream(std::ios_base::openmode mode
= std::ios_base::in | std::ios_base::out)
- : basic_ios_t(), base_t(0), m_buf(mode)
- { basic_ios_t::init(&m_buf); }
+ : //basic_ios_t() is called first (lefting it uninitialized) as it's a
+ //virtual base of basic_istream. The class will be initialized when
+ //basic_istream is constructed calling basic_ios_t::init().
+ //As bufferbuf_t's constructor does not throw there is no risk of
+ //calling the basic_ios_t's destructor without calling basic_ios_t::init()
+ bufferbuf_t(mode)
+ , base_t(&get_buf())
+ {}
//!Constructor. Assigns formatting buffer.
//!Does not throw.
- basic_bufferstream(CharT *buffer, std::size_t length,
+ basic_bufferstream(CharT *buf, std::size_t length,
std::ios_base::openmode mode
= std::ios_base::in | std::ios_base::out)
- : basic_ios_t(), base_t(0), m_buf(buffer, length, mode)
- { basic_ios_t::init(&m_buf); }
+ : //basic_ios_t() is called first (lefting it uninitialized) as it's a
+ //virtual base of basic_istream. The class will be initialized when
+ //basic_istream is constructed calling basic_ios_t::init().
+ //As bufferbuf_t's constructor does not throw there is no risk of
+ //calling the basic_ios_t's destructor without calling basic_ios_t::init()
+ bufferbuf_t(buf, length, mode)
+ , base_t(&get_buf())
+ {}
~basic_bufferstream(){}
@@ -407,22 +455,17 @@ class basic_bufferstream
//!Returns the address of the stored
//!stream buffer.
basic_bufferbuf<CharT, CharTraits>* rdbuf() const
- { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
+ { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); }
//!Returns the pointer and size of the internal buffer.
//!Does not throw.
std::pair<CharT *, std::size_t> buffer() const
- { return m_buf.buffer(); }
+ { return get_buf().buffer(); }
//!Sets the underlying buffer to a new value. Resets
//!stream position. Does not throw.
- void buffer(CharT *buffer, std::size_t length)
- { m_buf.buffer(buffer, length); }
-
- /// @cond
- private:
- basic_bufferbuf<CharT, CharTraits> m_buf;
- /// @endcond
+ void buffer(CharT *buf, std::size_t length)
+ { get_buf().buffer(buf, length); }
};
//Some typedefs to simplify usage
diff --git a/boost/interprocess/streams/vectorstream.hpp b/boost/interprocess/streams/vectorstream.hpp
index 3cee7200ab..94a75723b6 100644
--- a/boost/interprocess/streams/vectorstream.hpp
+++ b/boost/interprocess/streams/vectorstream.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -8,7 +8,7 @@
//
//////////////////////////////////////////////////////////////////////////////
//
-// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005.
+// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012.
// Changed internal SGI string to a generic, templatized vector. Added efficient
// internal buffer get/set/swap functions, so that we can obtain/establish the
// internal buffer without any reallocation or copy. Kill those temporaries!
@@ -36,6 +36,10 @@
#ifndef BOOST_INTERPROCESS_VECTORSTREAM_HPP
#define BOOST_INTERPROCESS_VECTORSTREAM_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -43,7 +47,7 @@
#include <ios>
#include <istream>
#include <ostream>
-#include <string> // char traits
+#include <string> // char traits
#include <cstddef> // ptrdiff_t
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
@@ -67,13 +71,13 @@ class basic_vectorbuf
typedef typename CharTraits::off_type off_type;
typedef CharTraits traits_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef std::basic_streambuf<char_type, traits_type> base_t;
basic_vectorbuf(const basic_vectorbuf&);
basic_vectorbuf & operator =(const basic_vectorbuf&);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor. Throws if vector_type default
@@ -92,15 +96,13 @@ class basic_vectorbuf
: base_t(), m_mode(mode), m_vect(param)
{ this->initialize_pointers(); }
- virtual ~basic_vectorbuf(){}
-
public:
//!Swaps the underlying vector with the passed vector.
//!This function resets the read/write position in the stream.
//!Does not throw.
void swap_vector(vector_type &vect)
- {
+ {
if (this->m_mode & std::ios_base::out){
//Update high water if necessary
//And resize vector to remove extra size
@@ -119,7 +121,7 @@ class basic_vectorbuf
//!Returns a const reference to the internal vector.
//!Does not throw.
const vector_type &vector() const
- {
+ {
if (this->m_mode & std::ios_base::out){
if (mp_high_water < base_t::pptr()){
//Restore the vector's size if necessary
@@ -163,7 +165,7 @@ class basic_vectorbuf
void clear()
{ m_vect.clear(); this->initialize_pointers(); }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
//Maximizes high watermark to the initial vector size,
//initializes read and write iostream buffers to the capacity
@@ -358,7 +360,7 @@ class basic_vectorbuf
std::ios_base::openmode m_mode;
mutable vector_type m_vect;
mutable char_type* mp_high_water;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!A basic_istream class that holds a character vector specified by CharVector
@@ -367,10 +369,10 @@ class basic_vectorbuf
//!boost::interprocess::basic_string
template <class CharVector, class CharTraits>
class basic_ivectorstream
- /// @cond
- : private basic_vectorbuf<CharVector, CharTraits>
- /// @endcond
- , public std::basic_istream<typename CharVector::value_type, CharTraits>
+ : public std::basic_istream<typename CharVector::value_type, CharTraits>
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ , private basic_vectorbuf<CharVector, CharTraits>
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
{
public:
typedef CharVector vector_type;
@@ -381,59 +383,65 @@ class basic_ivectorstream
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef basic_vectorbuf<CharVector, CharTraits> vectorbuf_t;
+ typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
typedef std::basic_istream<char_type, CharTraits> base_t;
- vectorbuf_t & m_buf() { return *this; }
- const vectorbuf_t & m_buf() const{ return *this; }
- /// @endcond
+ vectorbuf_t & get_buf() { return *this; }
+ const vectorbuf_t & get_buf() const{ return *this; }
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
+
//!Constructor. Throws if vector_type default
//!constructor throws.
basic_ivectorstream(std::ios_base::openmode mode = std::ios_base::in)
- : vectorbuf_t(mode | std::ios_base::in), base_t(&m_buf())
- {}
+ : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
+ //(via basic_ios::init() call in base_t's constructor) without the risk of a
+ //previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
+ , vectorbuf_t(mode | std::ios_base::in)
+ { this->base_t::rdbuf(&get_buf()); }
//!Constructor. Throws if vector_type(const VectorParameter &param)
//!throws.
template<class VectorParameter>
basic_ivectorstream(const VectorParameter &param,
std::ios_base::openmode mode = std::ios_base::in)
- : vectorbuf_t(param, mode | std::ios_base::in), base_t(&m_buf())
+ : vectorbuf_t(param, mode | std::ios_base::in)
+ //basic_ios_t() is constructed uninitialized as virtual base
+ //and initialized inside base_t calling basic_ios::init()
+ , base_t(&get_buf())
{}
- ~basic_ivectorstream(){};
-
public:
//!Returns the address of the stored
//!stream buffer.
basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
- { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf()); }
+ { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); }
//!Swaps the underlying vector with the passed vector.
//!This function resets the read position in the stream.
//!Does not throw.
void swap_vector(vector_type &vect)
- { m_buf().swap_vector(vect); }
+ { get_buf().swap_vector(vect); }
//!Returns a const reference to the internal vector.
//!Does not throw.
const vector_type &vector() const
- { return m_buf().vector(); }
+ { return get_buf().vector(); }
//!Calls reserve() method of the internal vector.
//!Resets the stream to the first position.
//!Throws if the internals vector's reserve throws.
void reserve(typename vector_type::size_type size)
- { m_buf().reserve(size); }
+ { get_buf().reserve(size); }
//!Calls clear() method of the internal vector.
//!Resets the stream to the first position.
void clear()
- { m_buf().clear(); }
+ { get_buf().clear(); }
};
//!A basic_ostream class that holds a character vector specified by CharVector
@@ -442,10 +450,10 @@ class basic_ivectorstream
//!boost::interprocess::basic_string
template <class CharVector, class CharTraits>
class basic_ovectorstream
- /// @cond
- : private basic_vectorbuf<CharVector, CharTraits>
- /// @endcond
- , public std::basic_ostream<typename CharVector::value_type, CharTraits>
+ : public std::basic_ostream<typename CharVector::value_type, CharTraits>
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ , private basic_vectorbuf<CharVector, CharTraits>
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
{
public:
typedef CharVector vector_type;
@@ -456,57 +464,61 @@ class basic_ovectorstream
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef basic_vectorbuf<CharVector, CharTraits> vectorbuf_t;
+ typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
typedef std::basic_ostream<char_type, CharTraits> base_t;
- vectorbuf_t & m_buf() { return *this; }
- const vectorbuf_t & m_buf()const { return *this; }
- /// @endcond
+ vectorbuf_t & get_buf() { return *this; }
+ const vectorbuf_t & get_buf()const { return *this; }
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor. Throws if vector_type default
//!constructor throws.
basic_ovectorstream(std::ios_base::openmode mode = std::ios_base::out)
- : vectorbuf_t(mode | std::ios_base::out), base_t(&m_buf())
- {}
+ : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
+ //(via basic_ios::init() call in base_t's constructor) without the risk of a
+ //previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
+ , vectorbuf_t(mode | std::ios_base::out)
+ { this->base_t::rdbuf(&get_buf()); }
//!Constructor. Throws if vector_type(const VectorParameter &param)
//!throws.
template<class VectorParameter>
basic_ovectorstream(const VectorParameter &param,
std::ios_base::openmode mode = std::ios_base::out)
- : vectorbuf_t(param, mode | std::ios_base::out), base_t(&m_buf())
- {}
-
- ~basic_ovectorstream(){}
+ : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
+ //(via basic_ios::init() call in base_t's constructor) without the risk of a
+ //previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
+ , vectorbuf_t(param, mode | std::ios_base::out)
+ { this->base_t::rdbuf(&get_buf()); }
public:
//!Returns the address of the stored
//!stream buffer.
basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
- { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf()); }
+ { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); }
//!Swaps the underlying vector with the passed vector.
//!This function resets the write position in the stream.
//!Does not throw.
void swap_vector(vector_type &vect)
- { m_buf().swap_vector(vect); }
+ { get_buf().swap_vector(vect); }
//!Returns a const reference to the internal vector.
//!Does not throw.
const vector_type &vector() const
- { return m_buf().vector(); }
+ { return get_buf().vector(); }
//!Calls reserve() method of the internal vector.
//!Resets the stream to the first position.
//!Throws if the internals vector's reserve throws.
void reserve(typename vector_type::size_type size)
- { m_buf().reserve(size); }
+ { get_buf().reserve(size); }
};
-
//!A basic_iostream class that holds a character vector specified by CharVector
//!template parameter as its formatting buffer. The vector must have
//!contiguous storage, like std::vector, boost::interprocess::vector or
@@ -514,7 +526,9 @@ class basic_ovectorstream
template <class CharVector, class CharTraits>
class basic_vectorstream
: public std::basic_iostream<typename CharVector::value_type, CharTraits>
-
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ , private basic_vectorbuf<CharVector, CharTraits>
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
{
public:
typedef CharVector vector_type;
@@ -525,61 +539,64 @@ class basic_vectorstream
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
- typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
- typedef std::basic_iostream<char_type, CharTraits> base_t;
- /// @endcond
+ typedef basic_vectorbuf<CharVector, CharTraits> vectorbuf_t;
+ typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
+ typedef std::basic_iostream<char_type, CharTraits> base_t;
+
+ vectorbuf_t & get_buf() { return *this; }
+ const vectorbuf_t & get_buf() const{ return *this; }
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor. Throws if vector_type default
//!constructor throws.
basic_vectorstream(std::ios_base::openmode mode
= std::ios_base::in | std::ios_base::out)
- : basic_ios_t(), base_t(0), m_buf(mode)
- { basic_ios_t::init(&m_buf); }
+ : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
+ //(via basic_ios::init() call in base_t's constructor) without the risk of a
+ //previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
+ , vectorbuf_t(mode)
+ { this->base_t::rdbuf(&get_buf()); }
//!Constructor. Throws if vector_type(const VectorParameter &param)
//!throws.
template<class VectorParameter>
basic_vectorstream(const VectorParameter &param, std::ios_base::openmode mode
= std::ios_base::in | std::ios_base::out)
- : basic_ios_t(), base_t(0), m_buf(param, mode)
- { basic_ios_t::init(&m_buf); }
-
- ~basic_vectorstream(){}
+ : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
+ //(via basic_ios::init() call in base_t's constructor) without the risk of a
+ //previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
+ , vectorbuf_t(param, mode)
+ { this->base_t::rdbuf(&get_buf()); }
public:
//Returns the address of the stored stream buffer.
basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
- { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf); }
+ { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); }
//!Swaps the underlying vector with the passed vector.
//!This function resets the read/write position in the stream.
//!Does not throw.
void swap_vector(vector_type &vect)
- { m_buf.swap_vector(vect); }
+ { get_buf().swap_vector(vect); }
//!Returns a const reference to the internal vector.
//!Does not throw.
const vector_type &vector() const
- { return m_buf.vector(); }
+ { return get_buf().vector(); }
//!Calls reserve() method of the internal vector.
//!Resets the stream to the first position.
//!Throws if the internals vector's reserve throws.
void reserve(typename vector_type::size_type size)
- { m_buf.reserve(size); }
+ { get_buf().reserve(size); }
//!Calls clear() method of the internal vector.
//!Resets the stream to the first position.
void clear()
- { m_buf.clear(); }
-
- /// @cond
- private:
- basic_vectorbuf<CharVector, CharTraits> m_buf;
- /// @endcond
+ { get_buf().clear(); }
};
//Some typedefs to simplify usage
diff --git a/boost/interprocess/sync/detail/common_algorithms.hpp b/boost/interprocess/sync/detail/common_algorithms.hpp
new file mode 100644
index 0000000000..76d1c5c9e8
--- /dev/null
+++ b/boost/interprocess/sync/detail/common_algorithms.hpp
@@ -0,0 +1,77 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SYNC_DETAIL_COMMON_ALGORITHMS_HPP
+#define BOOST_INTERPROCESS_SYNC_DETAIL_COMMON_ALGORITHMS_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/sync/spin/wait.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+template<class MutexType>
+bool try_based_timed_lock(MutexType &m, const boost::posix_time::ptime &abs_time)
+{
+ //Same as lock()
+ if(abs_time == boost::posix_time::pos_infin){
+ m.lock();
+ return true;
+ }
+ //Always try to lock to achieve POSIX guarantees:
+ // "Under no circumstance shall the function fail with a timeout if the mutex
+ // can be locked immediately. The validity of the abs_timeout parameter need not
+ // be checked if the mutex can be locked immediately."
+ else if(m.try_lock()){
+ return true;
+ }
+ else{
+ spin_wait swait;
+ while(microsec_clock::universal_time() < abs_time){
+ if(m.try_lock()){
+ return true;
+ }
+ swait.yield();
+ }
+ return false;
+ }
+}
+
+template<class MutexType>
+void try_based_lock(MutexType &m)
+{
+ if(!m.try_lock()){
+ spin_wait swait;
+ do{
+ if(m.try_lock()){
+ break;
+ }
+ else{
+ swait.yield();
+ }
+ }
+ while(1);
+ }
+}
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_SYNC_DETAIL_COMMON_ALGORITHMS_HPP
diff --git a/boost/interprocess/sync/detail/condition_algorithm_8a.hpp b/boost/interprocess/sync/detail/condition_algorithm_8a.hpp
index eaad671cdf..be93af7b8f 100644
--- a/boost/interprocess/sync/detail/condition_algorithm_8a.hpp
+++ b/boost/interprocess/sync/detail/condition_algorithm_8a.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,9 +11,14 @@
#ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
#define BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/interprocess/sync/detail/locks.hpp>
#include <limits>
namespace boost {
@@ -161,6 +166,15 @@ namespace ipcdetail {
// mutex_type &get_mtx_unblock_lock()
// };
//
+// Must be initialized as following
+//
+// get_nwaiters_blocked() == 0
+// get_nwaiters_gone() == 0
+// get_nwaiters_to_unblock() == 0
+// get_sem_block_queue() == initial count 0
+// get_sem_block_lock() == initial count 1
+// get_mtx_unblock_lock() (unlocked)
+//
template<class ConditionMembers>
class condition_algorithm_8a
{
@@ -174,16 +188,10 @@ class condition_algorithm_8a
typedef typename ConditionMembers::mutex_type mutex_type;
typedef typename ConditionMembers::integer_type integer_type;
- // nwaiters_blocked == 0
- // nwaiters_gone() == 0
- // nwaiters_to_unblock == 0
- // sem_block_queue() == initial count 0
- // sem_block_lock() == initial count 1
- // mtx_unblock_lock (unlocked)
-
public:
- template<class InterprocessMutex>
- static bool wait (ConditionMembers &data, bool timeout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
+ template<class Lock>
+ static bool wait ( ConditionMembers &data, Lock &lock
+ , bool timeout_enabled, const boost::posix_time::ptime &abs_time);
static void signal(ConditionMembers &data, bool broadcast);
};
@@ -235,9 +243,13 @@ inline void condition_algorithm_8a<ConditionMembers>::signal(ConditionMembers &d
}
template<class ConditionMembers>
-template<class InterprocessMutex>
+template<class Lock>
inline bool condition_algorithm_8a<ConditionMembers>::wait
- (ConditionMembers &data, bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mtxExternal)
+ ( ConditionMembers &data
+ , Lock &lock
+ , bool tout_enabled
+ , const boost::posix_time::ptime &abs_time
+ )
{
//Initialize to avoid warnings
integer_type nsignals_was_left = 0;
@@ -247,19 +259,13 @@ inline bool condition_algorithm_8a<ConditionMembers>::wait
++data.get_nwaiters_blocked();
data.get_sem_block_lock().post();
- struct scoped_unlock
- {
- InterprocessMutex & mut;
- scoped_unlock(InterprocessMutex & m)
- : mut(m)
- { m.unlock(); }
+ //Unlock external lock and program for relock
+ lock_inverter<Lock> inverted_lock(lock);
+ scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
- ~scoped_unlock()
- { mut.lock(); }
- } unlocker(mtxExternal);
-
-
- bool bTimedOut = tout_enabled ? !data.get_sem_block_queue().timed_wait(abs_time) : (data.get_sem_block_queue().wait(), false);
+ bool bTimedOut = tout_enabled
+ ? !data.get_sem_block_queue().timed_wait(abs_time)
+ : (data.get_sem_block_queue().wait(), false);
{
scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
@@ -290,7 +296,7 @@ inline bool condition_algorithm_8a<ConditionMembers>::wait
data.get_nwaiters_gone() = 0;
}
//locker's destructor triggers data.get_mtx_unblock_lock().unlock()
- }
+ }
if ( 1 == nsignals_was_left ) {
if ( 0 != nwaiters_was_gone ) {
@@ -302,11 +308,80 @@ inline bool condition_algorithm_8a<ConditionMembers>::wait
data.get_sem_block_lock().post(); // open the gate
}
- //mtxExternal.lock(); called from unlocker
+ //lock.lock(); called from unlocker destructor
return ( bTimedOut ) ? false : true;
}
+
+template<class ConditionMembers>
+class condition_8a_wrapper
+{
+ //Non-copyable
+ condition_8a_wrapper(const condition_8a_wrapper &);
+ condition_8a_wrapper &operator=(const condition_8a_wrapper &);
+
+ ConditionMembers m_data;
+ typedef ipcdetail::condition_algorithm_8a<ConditionMembers> algo_type;
+
+ public:
+
+ condition_8a_wrapper(){}
+
+ //Compiler-generated destructor is OK
+ //~condition_8a_wrapper(){}
+
+ ConditionMembers & get_members()
+ { return m_data; }
+
+ const ConditionMembers & get_members() const
+ { return m_data; }
+
+ void notify_one()
+ { algo_type::signal(m_data, false); }
+
+ void notify_all()
+ { algo_type::signal(m_data, true); }
+
+ template <typename L>
+ void wait(L& lock)
+ {
+ if (!lock)
+ throw lock_exception();
+ algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
+ }
+
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ {
+ if (!lock)
+ throw lock_exception();
+
+ while (!pred())
+ algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
+ }
+
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ {
+ if (!lock)
+ throw lock_exception();
+ return algo_type::wait(m_data, lock, true, abs_time);
+ }
+
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ {
+ if (!lock)
+ throw lock_exception();
+ while (!pred()){
+ if (!algo_type::wait(m_data, lock, true, abs_time))
+ return pred();
+ }
+ return true;
+ }
+};
+
} //namespace ipcdetail
} //namespace interprocess
} //namespace boost
diff --git a/boost/interprocess/sync/detail/condition_any_algorithm.hpp b/boost/interprocess/sync/detail/condition_any_algorithm.hpp
new file mode 100644
index 0000000000..5819acfa28
--- /dev/null
+++ b/boost/interprocess/sync/detail/condition_any_algorithm.hpp
@@ -0,0 +1,220 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
+#define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/interprocess/sync/detail/locks.hpp>
+#include <limits>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+//
+// Condition variable 'any' (able to use any type of external mutex)
+//
+// The code is based on Howard E. Hinnant's ISO C++ N2406 paper.
+// Many thanks to Howard for his support and comments.
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+// Required interface for ConditionAnyMembers
+// class ConditionAnyMembers
+// {
+// typedef implementation_defined mutex_type;
+// typedef implementation_defined condvar_type;
+//
+// condvar &get_condvar()
+// mutex_type &get_mutex()
+// };
+//
+// Must be initialized as following
+//
+// get_condvar() [no threads blocked]
+// get_mutex() [unlocked]
+
+template<class ConditionAnyMembers>
+class condition_any_algorithm
+{
+ private:
+ condition_any_algorithm();
+ ~condition_any_algorithm();
+ condition_any_algorithm(const condition_any_algorithm &);
+ condition_any_algorithm &operator=(const condition_any_algorithm &);
+
+ typedef typename ConditionAnyMembers::mutex_type mutex_type;
+ typedef typename ConditionAnyMembers::condvar_type condvar_type;
+
+ template <class Lock>
+ static void do_wait(ConditionAnyMembers &data, Lock& lock);
+
+ template <class Lock>
+ static bool do_timed_wait(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time);
+
+ public:
+ template<class Lock>
+ static bool wait ( ConditionAnyMembers &data, Lock &mut
+ , bool timeout_enabled, const boost::posix_time::ptime &abs_time);
+ static void signal( ConditionAnyMembers &data, bool broadcast);
+};
+
+template<class ConditionAnyMembers>
+void condition_any_algorithm<ConditionAnyMembers>::signal(ConditionAnyMembers &data, bool broadcast)
+{
+ scoped_lock<mutex_type> internal_lock(data.get_mutex());
+ if(broadcast){
+ data.get_condvar().notify_all();
+ }
+ else{
+ data.get_condvar().notify_one();
+ }
+}
+
+template<class ConditionAnyMembers>
+template<class Lock>
+bool condition_any_algorithm<ConditionAnyMembers>::wait
+ ( ConditionAnyMembers &data
+ , Lock &lock
+ , bool tout_enabled
+ , const boost::posix_time::ptime &abs_time)
+{
+ if(tout_enabled){
+ return condition_any_algorithm::do_timed_wait(data, lock, abs_time);
+ }
+ else{
+ condition_any_algorithm::do_wait(data, lock);
+ return true;
+ }
+}
+
+template<class ConditionAnyMembers>
+template <class Lock>
+void condition_any_algorithm<ConditionAnyMembers>::do_wait
+ (ConditionAnyMembers &data, Lock& lock)
+{
+ //lock internal before unlocking external to avoid race with a notifier
+ scoped_lock<mutex_type> internal_lock(data.get_mutex());
+ {
+ lock_inverter<Lock> inverted_lock(lock);
+ scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
+ { //unlock internal first to avoid deadlock with near simultaneous waits
+ scoped_lock<mutex_type> internal_unlock;
+ internal_lock.swap(internal_unlock);
+ data.get_condvar().wait(internal_unlock);
+ }
+ }
+}
+
+template<class ConditionAnyMembers>
+template <class Lock>
+bool condition_any_algorithm<ConditionAnyMembers>::do_timed_wait
+ (ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time)
+{
+ //lock internal before unlocking external to avoid race with a notifier
+ scoped_lock<mutex_type> internal_lock(data.get_mutex());
+ {
+ //Unlock external lock and program for relock
+ lock_inverter<Lock> inverted_lock(lock);
+ scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
+ { //unlock internal first to avoid deadlock with near simultaneous waits
+ scoped_lock<mutex_type> internal_unlock;
+ internal_lock.swap(internal_unlock);
+ return data.get_condvar().timed_wait(internal_unlock, abs_time);
+ }
+ }
+}
+
+
+template<class ConditionAnyMembers>
+class condition_any_wrapper
+{
+ //Non-copyable
+ condition_any_wrapper(const condition_any_wrapper &);
+ condition_any_wrapper &operator=(const condition_any_wrapper &);
+
+ ConditionAnyMembers m_data;
+ typedef ipcdetail::condition_any_algorithm<ConditionAnyMembers> algo_type;
+
+ public:
+
+ condition_any_wrapper(){}
+
+ ~condition_any_wrapper(){}
+
+ ConditionAnyMembers & get_members()
+ { return m_data; }
+
+ const ConditionAnyMembers & get_members() const
+ { return m_data; }
+
+ void notify_one()
+ { algo_type::signal(m_data, false); }
+
+ void notify_all()
+ { algo_type::signal(m_data, true); }
+
+ template <typename L>
+ void wait(L& lock)
+ {
+ if (!lock)
+ throw lock_exception();
+ algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
+ }
+
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ {
+ if (!lock)
+ throw lock_exception();
+
+ while (!pred())
+ algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
+ }
+
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ {
+ if (!lock)
+ throw lock_exception();
+ return algo_type::wait(m_data, lock, true, abs_time);
+ }
+
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ {
+ if (!lock)
+ throw lock_exception();
+ while (!pred()){
+ if (!algo_type::wait(m_data, lock, true, abs_time))
+ return pred();
+ }
+ return true;
+ }
+};
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
diff --git a/boost/interprocess/sync/detail/locks.hpp b/boost/interprocess/sync/detail/locks.hpp
new file mode 100644
index 0000000000..05652003a8
--- /dev/null
+++ b/boost/interprocess/sync/detail/locks.hpp
@@ -0,0 +1,97 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_LOCKS_HPP
+#define BOOST_INTERPROCESS_DETAIL_LOCKS_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+template<class Lock>
+class internal_mutex_lock
+{
+ typedef void (internal_mutex_lock::*unspecified_bool_type)();
+ public:
+
+ typedef typename Lock::mutex_type::internal_mutex_type mutex_type;
+
+
+ internal_mutex_lock(Lock &l)
+ : l_(l)
+ {}
+
+ mutex_type* mutex() const
+ { return l_ ? &l_.mutex()->internal_mutex() : 0; }
+
+ void lock() { l_.lock(); }
+
+ void unlock() { l_.unlock(); }
+
+ operator unspecified_bool_type() const
+ { return l_ ? &internal_mutex_lock::lock : 0; }
+
+ private:
+ Lock &l_;
+};
+
+template <class Lock>
+class lock_inverter
+{
+ Lock &l_;
+ public:
+ lock_inverter(Lock &l)
+ : l_(l)
+ {}
+ void lock() { l_.unlock(); }
+ void unlock() { l_.lock(); }
+};
+
+template <class Lock>
+class lock_to_sharable
+{
+ Lock &l_;
+
+ public:
+ explicit lock_to_sharable(Lock &l)
+ : l_(l)
+ {}
+ void lock() { l_.lock_sharable(); }
+ bool try_lock(){ return l_.try_lock_sharable(); }
+ void unlock() { l_.unlock_sharable(); }
+};
+
+template <class Lock>
+class lock_to_wait
+{
+ Lock &l_;
+
+ public:
+ explicit lock_to_wait(Lock &l)
+ : l_(l)
+ {}
+ void lock() { l_.wait(); }
+ bool try_lock(){ return l_.try_wait(); }
+};
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_LOCKS_HPP
diff --git a/boost/interprocess/sync/file_lock.hpp b/boost/interprocess/sync/file_lock.hpp
index e0f75465fb..e8d3903dbe 100644
--- a/boost/interprocess/sync/file_lock.hpp
+++ b/boost/interprocess/sync/file_lock.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_FILE_LOCK_HPP
#define BOOST_INTERPROCESS_FILE_LOCK_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -21,7 +21,9 @@
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
-#include <boost/move/move.hpp>
+#include <boost/interprocess/sync/detail/common_algorithms.hpp>
+#include <boost/interprocess/sync/detail/locks.hpp>
+#include <boost/move/utility_core.hpp>
//!\file
//!Describes a class that wraps file locking capabilities.
@@ -37,10 +39,10 @@ namespace interprocess {
//!process so just use file locks to synchronize threads from different processes.
class file_lock
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
BOOST_MOVABLE_BUT_NOT_COPYABLE(file_lock)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructs an empty file mapping.
@@ -64,10 +66,10 @@ class file_lock
//!After the call, "moved" does not represent any file mapping.
//!Does not throw
file_lock &operator=(BOOST_RV_REF(file_lock) moved)
- {
+ {
file_lock tmp(boost::move(moved));
this->swap(tmp);
- return *this;
+ return *this;
}
//!Closes a file lock. Does not throw.
@@ -81,7 +83,7 @@ class file_lock
m_file_hnd = other.m_file_hnd;
other.m_file_hnd = tmp;
}
-
+
//Exclusive locking
//!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
@@ -137,66 +139,11 @@ class file_lock
//!Effects: The calling thread releases the sharable ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_sharable();
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
file_handle_t m_file_hnd;
- bool timed_acquire_file_lock
- (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time)
- {
- //Obtain current count and target time
- boost::posix_time::ptime now = microsec_clock::universal_time();
- using namespace boost::detail;
-
- if(now >= abs_time) return false;
-
- do{
- if(!ipcdetail::try_acquire_file_lock(hnd, acquired))
- return false;
-
- if(acquired)
- return true;
- else{
- now = microsec_clock::universal_time();
-
- if(now >= abs_time){
- acquired = false;
- return true;
- }
- // relinquish current time slice
- ipcdetail::thread_yield();
- }
- }while (true);
- }
-
- bool timed_acquire_file_lock_sharable
- (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time)
- {
- //Obtain current count and target time
- boost::posix_time::ptime now = microsec_clock::universal_time();
- using namespace boost::detail;
-
- if(now >= abs_time) return false;
-
- do{
- if(!ipcdetail::try_acquire_file_lock_sharable(hnd, acquired))
- return false;
-
- if(acquired)
- return true;
- else{
- now = microsec_clock::universal_time();
-
- if(now >= abs_time){
- acquired = false;
- return true;
- }
- // relinquish current time slice
- ipcdetail::thread_yield();
- }
- }while (true);
- }
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
inline file_lock::file_lock(const char *name)
@@ -236,18 +183,7 @@ inline bool file_lock::try_lock()
}
inline bool file_lock::timed_lock(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
- bool result;
- if(!this->timed_acquire_file_lock(m_file_hnd, result, abs_time)){
- error_info err(system_error_code());
- throw interprocess_exception(err);
- }
- return result;
-}
+{ return ipcdetail::try_based_timed_lock(*this, abs_time); }
inline void file_lock::unlock()
{
@@ -277,16 +213,8 @@ inline bool file_lock::try_lock_sharable()
inline bool file_lock::timed_lock_sharable(const boost::posix_time::ptime &abs_time)
{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock_sharable();
- return true;
- }
- bool result;
- if(!this->timed_acquire_file_lock_sharable(m_file_hnd, result, abs_time)){
- error_info err(system_error_code());
- throw interprocess_exception(err);
- }
- return result;
+ ipcdetail::lock_to_sharable<file_lock> lsh(*this);
+ return ipcdetail::try_based_timed_lock(lsh, abs_time);
}
inline void file_lock::unlock_sharable()
diff --git a/boost/interprocess/sync/interprocess_condition.hpp b/boost/interprocess/sync/interprocess_condition.hpp
index 9d0bea640e..19fba30762 100644
--- a/boost/interprocess/sync/interprocess_condition.hpp
+++ b/boost/interprocess/sync/interprocess_condition.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,17 +11,18 @@
#ifndef BOOST_INTERPROCESS_CONDITION_HPP
#define BOOST_INTERPROCESS_CONDITION_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/detail/locks.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/limits.hpp>
#include <boost/assert.hpp>
@@ -38,37 +39,49 @@
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
#endif
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!\file
//!Describes process-shared variables interprocess_condition class
namespace boost {
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
namespace posix_time
{ class ptime; }
+#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
namespace interprocess {
class named_condition;
//!This class is a condition variable that can be placed in shared memory or
//!memory mapped files.
+//!Destroys the object of type std::condition_variable_any
+//!
+//!Unlike std::condition_variable in C++11, it is NOT safe to invoke the destructor if all
+//!threads have been only notified. It is required that they have exited their respective wait
+//!functions.
class interprocess_condition
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
interprocess_condition(const interprocess_condition &);
interprocess_condition &operator=(const interprocess_condition &);
friend class named_condition;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
public:
//!Constructs a interprocess_condition. On error throws interprocess_exception.
- interprocess_condition(){}
+ interprocess_condition()
+ {}
//!Destroys *this
//!liberating system resources.
- ~interprocess_condition(){}
+ ~interprocess_condition()
+ {}
//!If there is a thread waiting on *this, change that
//!thread's state to ready. Otherwise there is no effect.
@@ -86,9 +99,8 @@ class interprocess_condition
template <typename L>
void wait(L& lock)
{
- if (!lock)
- throw lock_exception();
- this->do_wait(*lock.mutex());
+ ipcdetail::internal_mutex_lock<L> internal_lock(lock);
+ m_condition.wait(internal_lock);
}
//!The same as:
@@ -96,11 +108,8 @@ class interprocess_condition
template <typename L, typename Pr>
void wait(L& lock, Pr pred)
{
- if (!lock)
- throw lock_exception();
-
- while (!pred())
- this->do_wait(*lock.mutex());
+ ipcdetail::internal_mutex_lock<L> internal_lock(lock);
+ m_condition.wait(internal_lock, pred);
}
//!Releases the lock on the interprocess_mutex object associated with lock, blocks
@@ -111,13 +120,8 @@ class interprocess_condition
template <typename L>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock);
- return true;
- }
- if (!lock)
- throw lock_exception();
- return this->do_timed_wait(abs_time, *lock.mutex());
+ ipcdetail::internal_mutex_lock<L> internal_lock(lock);
+ return m_condition.timed_wait(internal_lock, abs_time);
}
//!The same as: while (!pred()) {
@@ -126,27 +130,11 @@ class interprocess_condition
template <typename L, typename Pr>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock, pred);
- return true;
- }
- if (!lock)
- throw lock_exception();
- while (!pred()){
- if (!this->do_timed_wait(abs_time, *lock.mutex()))
- return pred();
- }
-
- return true;
+ ipcdetail::internal_mutex_lock<L> internal_lock(lock);
+ return m_condition.timed_wait(internal_lock, abs_time, pred);
}
- /// @cond
-
- void do_wait(interprocess_mutex &mut)
- { m_condition.do_wait(mut.mutex); }
-
- bool do_timed_wait(const boost::posix_time::ptime &abs_time, interprocess_mutex &mut)
- { return m_condition.do_timed_wait(abs_time, mut.mutex); }
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
@@ -161,7 +149,7 @@ class interprocess_condition
#else
#error "Unknown platform for interprocess_mutex"
#endif
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
} //namespace interprocess
diff --git a/boost/interprocess/sync/interprocess_condition_any.hpp b/boost/interprocess/sync/interprocess_condition_any.hpp
new file mode 100644
index 0000000000..093d69cda2
--- /dev/null
+++ b/boost/interprocess/sync/interprocess_condition_any.hpp
@@ -0,0 +1,133 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONDITION_ANY_HPP
+#define BOOST_INTERPROCESS_CONDITION_ANY_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/interprocess_condition.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/sync/detail/condition_any_algorithm.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!\file
+//!Describes process-shared variables interprocess_condition_any class
+
+namespace boost {
+
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+namespace posix_time
+{ class ptime; }
+
+#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+namespace interprocess {
+
+//!This class is a condition variable that can be placed in shared memory or
+//!memory mapped files.
+//!
+//!The interprocess_condition_any class is a generalization of interprocess_condition.
+//!Whereas interprocess_condition works only on Locks with mutex_type == interprocess_mutex
+//!interprocess_condition_any can operate on any user-defined lock that meets the BasicLockable
+//!requirements (lock()/unlock() member functions).
+//!
+//!Unlike std::condition_variable_any in C++11, it is NOT safe to invoke the destructor if all
+//!threads have been only notified. It is required that they have exited their respective wait
+//!functions.
+class interprocess_condition_any
+{
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ //Non-copyable
+ interprocess_condition_any(const interprocess_condition_any &);
+ interprocess_condition_any &operator=(const interprocess_condition_any &);
+
+ class members
+ {
+ public:
+ typedef interprocess_condition condvar_type;
+ typedef interprocess_mutex mutex_type;
+
+ condvar_type &get_condvar() { return m_cond; }
+ mutex_type &get_mutex() { return m_mut; }
+
+ private:
+ condvar_type m_cond;
+ mutex_type m_mut;
+ };
+
+ ipcdetail::condition_any_wrapper<members> m_cond;
+
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ public:
+ //!Constructs a interprocess_condition_any. On error throws interprocess_exception.
+ interprocess_condition_any(){}
+
+ //!Destroys *this
+ //!liberating system resources.
+ ~interprocess_condition_any(){}
+
+ //!If there is a thread waiting on *this, change that
+ //!thread's state to ready. Otherwise there is no effect.
+ void notify_one()
+ { m_cond.notify_one(); }
+
+ //!Change the state of all threads waiting on *this to ready.
+ //!If there are no waiting threads, notify_all() has no effect.
+ void notify_all()
+ { m_cond.notify_all(); }
+
+ //!Releases the lock on the interprocess_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), and then reacquires the lock.
+ template <typename L>
+ void wait(L& lock)
+ { m_cond.wait(lock); }
+
+ //!The same as:
+ //!while (!pred()) wait(lock)
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ { m_cond.wait(lock, pred); }
+
+ //!Releases the lock on the interprocess_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
+ //!and then reacquires the lock.
+ //!Returns: false if time abs_time is reached, otherwise true.
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ { return m_cond.timed_wait(lock, abs_time); }
+
+ //!The same as: while (!pred()) {
+ //! if (!timed_wait(lock, abs_time)) return pred();
+ //! } return true;
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ { return m_cond.timed_wait(lock, abs_time, pred); }
+};
+
+} //namespace interprocess
+} // namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_CONDITION_ANY_HPP
diff --git a/boost/interprocess/sync/interprocess_mutex.hpp b/boost/interprocess/sync/interprocess_mutex.hpp
index 8110c8472b..f4f7258ad8 100644
--- a/boost/interprocess/sync/interprocess_mutex.hpp
+++ b/boost/interprocess/sync/interprocess_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -15,9 +15,9 @@
#ifndef BOOST_INTERPROCESS_MUTEX_HPP
#define BOOST_INTERPROCESS_MUTEX_HPP
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -50,7 +50,7 @@ class mutex_traits;
#endif
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!\file
//!Describes a mutex class that can be placed in memory shared by
@@ -65,12 +65,31 @@ class interprocess_condition;
//!shared between processes. Allows timed lock tries
class interprocess_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
interprocess_mutex(const interprocess_mutex &);
interprocess_mutex &operator=(const interprocess_mutex &);
friend class interprocess_condition;
- /// @endcond
+
+ public:
+ #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
+ #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
+ typedef ipcdetail::spin_mutex internal_mutex_type;
+ private:
+ friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_mutex>;
+ void take_ownership(){ m_mutex.take_ownership(); }
+ public:
+ #elif defined(BOOST_INTERPROCESS_USE_POSIX)
+ #undef BOOST_INTERPROCESS_USE_POSIX
+ typedef ipcdetail::posix_mutex internal_mutex_type;
+ #elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
+ #undef BOOST_INTERPROCESS_USE_WINDOWS
+ typedef ipcdetail::windows_mutex internal_mutex_type;
+ #else
+ #error "Unknown platform for interprocess_mutex"
+ #endif
+
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor.
@@ -107,24 +126,17 @@ class interprocess_mutex
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//!Throws: interprocess_exception on error.
void unlock();
- /// @cond
- private:
- #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
- #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
- friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_mutex>;
- void take_ownership(){ mutex.take_ownership(); }
- ipcdetail::spin_mutex mutex;
- #elif defined(BOOST_INTERPROCESS_USE_POSIX)
- #undef BOOST_INTERPROCESS_USE_POSIX
- ipcdetail::posix_mutex mutex;
- #elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
- #undef BOOST_INTERPROCESS_USE_WINDOWS
- ipcdetail::windows_mutex mutex;
- #else
- #error "Unknown platform for interprocess_mutex"
- #endif
- /// @endcond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ internal_mutex_type &internal_mutex()
+ { return m_mutex; }
+
+ const internal_mutex_type &internal_mutex() const
+ { return m_mutex; }
+
+ private:
+ internal_mutex_type m_mutex;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
} //namespace interprocess {
@@ -144,23 +156,25 @@ inline void interprocess_mutex::lock()
boost::posix_time::ptime wait_time
= boost::posix_time::microsec_clock::universal_time()
+ boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
- if (!mutex.timed_lock(wait_time))
+ if (!m_mutex.timed_lock(wait_time))
{
- throw interprocess_exception(timeout_when_locking_error, "Interprocess mutex timeout when locking. Possible deadlock: owner died without unlocking?");
+ throw interprocess_exception(timeout_when_locking_error
+ , "Interprocess mutex timeout when locking. Possible deadlock: "
+ "owner died without unlocking?");
}
#else
- mutex.lock();
+ m_mutex.lock();
#endif
}
inline bool interprocess_mutex::try_lock()
-{ return mutex.try_lock(); }
+{ return m_mutex.try_lock(); }
inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
-{ return mutex.timed_lock(abs_time); }
+{ return m_mutex.timed_lock(abs_time); }
inline void interprocess_mutex::unlock()
-{ mutex.unlock(); }
+{ m_mutex.unlock(); }
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/sync/interprocess_recursive_mutex.hpp b/boost/interprocess/sync/interprocess_recursive_mutex.hpp
index 3079108645..fcc0e97228 100644
--- a/boost/interprocess/sync/interprocess_recursive_mutex.hpp
+++ b/boost/interprocess/sync/interprocess_recursive_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -27,9 +27,9 @@
#ifndef BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
#define BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -64,7 +64,7 @@ class mutex_traits;
#endif
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!\file
//!Describes interprocess_recursive_mutex and shared_recursive_try_mutex classes
@@ -77,11 +77,11 @@ namespace interprocess {
//!process. Allows timed lock tries
class interprocess_recursive_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
interprocess_recursive_mutex(const interprocess_recursive_mutex &);
interprocess_recursive_mutex &operator=(const interprocess_recursive_mutex &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor.
//!Throws interprocess_exception on error.
@@ -116,7 +116,7 @@ class interprocess_recursive_mutex
//! same number of times it is locked.
//!Throws: interprocess_exception on error.
void unlock();
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
@@ -133,7 +133,7 @@ class interprocess_recursive_mutex
#else
#error "Unknown platform for interprocess_mutex"
#endif
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
} //namespace interprocess {
diff --git a/boost/interprocess/sync/interprocess_semaphore.hpp b/boost/interprocess/sync/interprocess_semaphore.hpp
index 2a2f34fdcf..df65193ceb 100644
--- a/boost/interprocess/sync/interprocess_semaphore.hpp
+++ b/boost/interprocess/sync/interprocess_semaphore.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,9 +11,9 @@
#ifndef BOOST_INTERPROCESS_SEMAPHORE_HPP
#define BOOST_INTERPROCESS_SEMAPHORE_HPP
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -37,7 +37,7 @@
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
#endif
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!\file
//!Describes a interprocess_semaphore class for inter-process synchronization
@@ -49,11 +49,11 @@ namespace interprocess {
//!shared between processes. Allows timed lock tries
class interprocess_semaphore
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
interprocess_semaphore(const interprocess_semaphore &);
interprocess_semaphore &operator=(const interprocess_semaphore &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Creates a interprocess_semaphore with the given initial count.
//!interprocess_exception if there is an error.*/
@@ -87,7 +87,7 @@ class interprocess_semaphore
//!Returns the interprocess_semaphore count
// int get_count() const;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
@@ -99,7 +99,7 @@ class interprocess_semaphore
#undef BOOST_INTERPROCESS_USE_POSIX
ipcdetail::posix_semaphore m_sem;
#endif //#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
} //namespace interprocess {
diff --git a/boost/interprocess/sync/interprocess_sharable_mutex.hpp b/boost/interprocess/sync/interprocess_sharable_mutex.hpp
new file mode 100644
index 0000000000..fbaf22a45f
--- /dev/null
+++ b/boost/interprocess/sync/interprocess_sharable_mutex.hpp
@@ -0,0 +1,345 @@
+//////////////////////////////////////////////////////////////////////////////
+// Code based on Howard Hinnant's shared_mutex class
+//
+// (C) Copyright Howard Hinnant 2007-2010. Distributed under the Boost
+// Software License, Version 1.0. (see http://www.boost.org/LICENSE_1_0.txt)
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP
+#define BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/interprocess_condition.hpp>
+#include <climits>
+
+
+//!\file
+//!Describes interprocess_sharable_mutex class
+
+namespace boost {
+namespace interprocess {
+
+//!Wraps a interprocess_sharable_mutex that can be placed in shared memory and can be
+//!shared between processes. Allows timed lock tries
+class interprocess_sharable_mutex
+{
+ //Non-copyable
+ interprocess_sharable_mutex(const interprocess_sharable_mutex &);
+ interprocess_sharable_mutex &operator=(const interprocess_sharable_mutex &);
+
+ friend class interprocess_condition;
+ public:
+
+ //!Constructs the sharable lock.
+ //!Throws interprocess_exception on error.
+ interprocess_sharable_mutex();
+
+ //!Destroys the sharable lock.
+ //!Does not throw.
+ ~interprocess_sharable_mutex();
+
+ //Exclusive locking
+
+ //!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
+ //! and if another thread has exclusive or sharable ownership of
+ //! the mutex, it waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! without waiting. If no other thread has exclusive or sharable
+ //! ownership of the mutex this succeeds.
+ //!Returns: If it can acquire exclusive ownership immediately returns true.
+ //! If it has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive or sharable
+ //! ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The calling thread releases the exclusive ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock();
+
+ //Sharable locking
+
+ //!Effects: The calling thread tries to obtain sharable ownership of the mutex,
+ //! and if another thread has exclusive ownership of the mutex,
+ //! waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! without waiting. If no other thread has exclusive ownership
+ //! of the mutex this succeeds.
+ //!Returns: If it can acquire sharable ownership immediately returns true. If it
+ //! has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive
+ //! ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have sharable ownership of the mutex.
+ //!Effects: The calling thread releases the sharable ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_sharable();
+
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ private:
+ typedef scoped_lock<interprocess_mutex> scoped_lock_t;
+
+ //Pack all the control data in a word to be able
+ //to use atomic instructions in the future
+ struct control_word_t
+ {
+ unsigned exclusive_in : 1;
+ unsigned num_shared : sizeof(unsigned)*CHAR_BIT-1;
+ } m_ctrl;
+
+ interprocess_mutex m_mut;
+ interprocess_condition m_first_gate;
+ interprocess_condition m_second_gate;
+
+ private:
+ //Rollback structures for exceptions or failure return values
+ struct exclusive_rollback
+ {
+ exclusive_rollback(control_word_t &ctrl
+ ,interprocess_condition &first_gate)
+ : mp_ctrl(&ctrl), m_first_gate(first_gate)
+ {}
+
+ void release()
+ { mp_ctrl = 0; }
+
+ ~exclusive_rollback()
+ {
+ if(mp_ctrl){
+ mp_ctrl->exclusive_in = 0;
+ m_first_gate.notify_all();
+ }
+ }
+ control_word_t *mp_ctrl;
+ interprocess_condition &m_first_gate;
+ };
+
+ template<int Dummy>
+ struct base_constants_t
+ {
+ static const unsigned max_readers
+ = ~(unsigned(1) << (sizeof(unsigned)*CHAR_BIT-1));
+ };
+ typedef base_constants_t<0> constants;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+};
+
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+template <int Dummy>
+const unsigned interprocess_sharable_mutex::base_constants_t<Dummy>::max_readers;
+
+inline interprocess_sharable_mutex::interprocess_sharable_mutex()
+{
+ this->m_ctrl.exclusive_in = 0;
+ this->m_ctrl.num_shared = 0;
+}
+
+inline interprocess_sharable_mutex::~interprocess_sharable_mutex()
+{}
+
+inline void interprocess_sharable_mutex::lock()
+{
+ scoped_lock_t lck(m_mut);
+
+ //The exclusive lock must block in the first gate
+ //if an exclusive lock has been acquired
+ while (this->m_ctrl.exclusive_in){
+ this->m_first_gate.wait(lck);
+ }
+
+ //Mark that exclusive lock has been acquired
+ this->m_ctrl.exclusive_in = 1;
+
+ //Prepare rollback
+ exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
+
+ //Now wait until all readers are gone
+ while (this->m_ctrl.num_shared){
+ this->m_second_gate.wait(lck);
+ }
+ rollback.release();
+}
+
+inline bool interprocess_sharable_mutex::try_lock()
+{
+ scoped_lock_t lck(m_mut, try_to_lock);
+
+ //If we can't lock or any has there is any exclusive
+ //or sharable mark return false;
+ if(!lck.owns()
+ || this->m_ctrl.exclusive_in
+ || this->m_ctrl.num_shared){
+ return false;
+ }
+ this->m_ctrl.exclusive_in = 1;
+ return true;
+}
+
+inline bool interprocess_sharable_mutex::timed_lock
+ (const boost::posix_time::ptime &abs_time)
+{
+ scoped_lock_t lck(m_mut, abs_time);
+ if(!lck.owns()) return false;
+
+ //The exclusive lock must block in the first gate
+ //if an exclusive lock has been acquired
+ while (this->m_ctrl.exclusive_in){
+ //Mutexes and condvars handle just fine infinite abs_times
+ //so avoid checking it here
+ if(!this->m_first_gate.timed_wait(lck, abs_time)){
+ if(this->m_ctrl.exclusive_in){
+ return false;
+ }
+ break;
+ }
+ }
+
+ //Mark that exclusive lock has been acquired
+ this->m_ctrl.exclusive_in = 1;
+
+ //Prepare rollback
+ exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
+
+ //Now wait until all readers are gone
+ while (this->m_ctrl.num_shared){
+ //Mutexes and condvars handle just fine infinite abs_times
+ //so avoid checking it here
+ if(!this->m_second_gate.timed_wait(lck, abs_time)){
+ if(this->m_ctrl.num_shared){
+ return false;
+ }
+ break;
+ }
+ }
+ rollback.release();
+ return true;
+}
+
+inline void interprocess_sharable_mutex::unlock()
+{
+ scoped_lock_t lck(m_mut);
+ this->m_ctrl.exclusive_in = 0;
+ this->m_first_gate.notify_all();
+}
+
+//Sharable locking
+
+inline void interprocess_sharable_mutex::lock_sharable()
+{
+ scoped_lock_t lck(m_mut);
+
+ //The sharable lock must block in the first gate
+ //if an exclusive lock has been acquired
+ //or there are too many sharable locks
+ while(this->m_ctrl.exclusive_in
+ || this->m_ctrl.num_shared == constants::max_readers){
+ this->m_first_gate.wait(lck);
+ }
+
+ //Increment sharable count
+ ++this->m_ctrl.num_shared;
+}
+
+inline bool interprocess_sharable_mutex::try_lock_sharable()
+{
+ scoped_lock_t lck(m_mut, try_to_lock);
+
+ //The sharable lock must fail
+ //if an exclusive lock has been acquired
+ //or there are too many sharable locks
+ if(!lck.owns()
+ || this->m_ctrl.exclusive_in
+ || this->m_ctrl.num_shared == constants::max_readers){
+ return false;
+ }
+
+ //Increment sharable count
+ ++this->m_ctrl.num_shared;
+ return true;
+}
+
+inline bool interprocess_sharable_mutex::timed_lock_sharable
+ (const boost::posix_time::ptime &abs_time)
+{
+ scoped_lock_t lck(m_mut, abs_time);
+ if(!lck.owns()) return false;
+
+ //The sharable lock must block in the first gate
+ //if an exclusive lock has been acquired
+ //or there are too many sharable locks
+ while (this->m_ctrl.exclusive_in
+ || this->m_ctrl.num_shared == constants::max_readers){
+ //Mutexes and condvars handle just fine infinite abs_times
+ //so avoid checking it here
+ if(!this->m_first_gate.timed_wait(lck, abs_time)){
+ if(this->m_ctrl.exclusive_in
+ || this->m_ctrl.num_shared == constants::max_readers){
+ return false;
+ }
+ break;
+ }
+ }
+
+ //Increment sharable count
+ ++this->m_ctrl.num_shared;
+ return true;
+}
+
+inline void interprocess_sharable_mutex::unlock_sharable()
+{
+ scoped_lock_t lck(m_mut);
+ //Decrement sharable count
+ --this->m_ctrl.num_shared;
+ if (this->m_ctrl.num_shared == 0){
+ this->m_second_gate.notify_one();
+ }
+ //Check if there are blocked sharables because of
+ //there were too many sharables
+ else if(this->m_ctrl.num_shared == (constants::max_readers-1)){
+ this->m_first_gate.notify_all();
+ }
+}
+
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP
diff --git a/boost/interprocess/sync/interprocess_upgradable_mutex.hpp b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp
index 8d5a452626..b90c71ef7f 100644
--- a/boost/interprocess/sync/interprocess_upgradable_mutex.hpp
+++ b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp
@@ -1,6 +1,8 @@
-//////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// Code based on Howard Hinnant's upgrade_mutex class
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +13,7 @@
#ifndef BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
#define BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -195,7 +197,7 @@ class interprocess_upgradable_mutex
//!Throws: An exception derived from interprocess_exception on error.
bool try_unlock_sharable_and_lock_upgradable();
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef scoped_lock<interprocess_mutex> scoped_lock_t;
@@ -249,7 +251,7 @@ class interprocess_upgradable_mutex
if(mp_ctrl){
//Recover upgradable lock
mp_ctrl->upgradable_in = 1;
- ++mp_ctrl->num_upr_shar;
+ ++mp_ctrl->num_upr_shar;
//Execute the second half of exclusive locking
mp_ctrl->exclusive_in = 0;
}
@@ -264,10 +266,10 @@ class interprocess_upgradable_mutex
= ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2));
};
typedef base_constants_t<0> constants;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template <int Dummy>
const unsigned interprocess_upgradable_mutex::base_constants_t<Dummy>::max_readers;
@@ -284,12 +286,12 @@ inline interprocess_upgradable_mutex::~interprocess_upgradable_mutex()
inline void interprocess_upgradable_mutex::lock()
{
- scoped_lock_t lock(m_mut);
+ scoped_lock_t lck(m_mut);
//The exclusive lock must block in the first gate
//if an exclusive or upgradable lock has been acquired
while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
- this->m_first_gate.wait(lock);
+ this->m_first_gate.wait(lck);
}
//Mark that exclusive lock has been acquired
@@ -300,18 +302,18 @@ inline void interprocess_upgradable_mutex::lock()
//Now wait until all readers are gone
while (this->m_ctrl.num_upr_shar){
- this->m_second_gate.wait(lock);
+ this->m_second_gate.wait(lck);
}
rollback.release();
}
inline bool interprocess_upgradable_mutex::try_lock()
{
- scoped_lock_t lock(m_mut, try_to_lock);
+ scoped_lock_t lck(m_mut, try_to_lock);
//If we can't lock or any has there is any exclusive, upgradable
//or sharable mark return false;
- if(!lock.owns()
+ if(!lck.owns()
|| this->m_ctrl.exclusive_in
|| this->m_ctrl.num_upr_shar){
return false;
@@ -323,18 +325,20 @@ inline bool interprocess_upgradable_mutex::try_lock()
inline bool interprocess_upgradable_mutex::timed_lock
(const boost::posix_time::ptime &abs_time)
{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
- scoped_lock_t lock(m_mut, abs_time);
- if(!lock.owns()) return false;
+ //Mutexes and condvars handle just fine infinite abs_times
+ //so avoid checking it here
+ scoped_lock_t lck(m_mut, abs_time);
+ if(!lck.owns()) return false;
//The exclusive lock must block in the first gate
//if an exclusive or upgradable lock has been acquired
while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
- if(!this->m_first_gate.timed_wait(lock, abs_time))
- return !(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in);
+ if(!this->m_first_gate.timed_wait(lck, abs_time)){
+ if(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
+ return false;
+ }
+ break;
+ }
}
//Mark that exclusive lock has been acquired
@@ -345,8 +349,11 @@ inline bool interprocess_upgradable_mutex::timed_lock
//Now wait until all readers are gone
while (this->m_ctrl.num_upr_shar){
- if(!this->m_second_gate.timed_wait(lock, abs_time)){
- return !(this->m_ctrl.num_upr_shar);
+ if(!this->m_second_gate.timed_wait(lck, abs_time)){
+ if(this->m_ctrl.num_upr_shar){
+ return false;
+ }
+ break;
}
}
rollback.release();
@@ -355,7 +362,7 @@ inline bool interprocess_upgradable_mutex::timed_lock
inline void interprocess_upgradable_mutex::unlock()
{
- scoped_lock_t lock(m_mut);
+ scoped_lock_t lck(m_mut);
this->m_ctrl.exclusive_in = 0;
this->m_first_gate.notify_all();
}
@@ -364,14 +371,14 @@ inline void interprocess_upgradable_mutex::unlock()
inline void interprocess_upgradable_mutex::lock_upgradable()
{
- scoped_lock_t lock(m_mut);
+ scoped_lock_t lck(m_mut);
//The upgradable lock must block in the first gate
//if an exclusive or upgradable lock has been acquired
//or there are too many sharable locks
while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in
|| this->m_ctrl.num_upr_shar == constants::max_readers){
- this->m_first_gate.wait(lock);
+ this->m_first_gate.wait(lck);
}
//Mark that upgradable lock has been acquired
@@ -382,12 +389,12 @@ inline void interprocess_upgradable_mutex::lock_upgradable()
inline bool interprocess_upgradable_mutex::try_lock_upgradable()
{
- scoped_lock_t lock(m_mut, try_to_lock);
+ scoped_lock_t lck(m_mut, try_to_lock);
//The upgradable lock must fail
//if an exclusive or upgradable lock has been acquired
//or there are too many sharable locks
- if(!lock.owns()
+ if(!lck.owns()
|| this->m_ctrl.exclusive_in
|| this->m_ctrl.upgradable_in
|| this->m_ctrl.num_upr_shar == constants::max_readers){
@@ -404,12 +411,10 @@ inline bool interprocess_upgradable_mutex::try_lock_upgradable()
inline bool interprocess_upgradable_mutex::timed_lock_upgradable
(const boost::posix_time::ptime &abs_time)
{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock_upgradable();
- return true;
- }
- scoped_lock_t lock(m_mut, abs_time);
- if(!lock.owns()) return false;
+ //Mutexes and condvars handle just fine infinite abs_times
+ //so avoid checking it here
+ scoped_lock_t lck(m_mut, abs_time);
+ if(!lck.owns()) return false;
//The upgradable lock must block in the first gate
//if an exclusive or upgradable lock has been acquired
@@ -417,10 +422,13 @@ inline bool interprocess_upgradable_mutex::timed_lock_upgradable
while(this->m_ctrl.exclusive_in
|| this->m_ctrl.upgradable_in
|| this->m_ctrl.num_upr_shar == constants::max_readers){
- if(!this->m_first_gate.timed_wait(lock, abs_time)){
- return!(this->m_ctrl.exclusive_in
- || this->m_ctrl.upgradable_in
- || this->m_ctrl.num_upr_shar == constants::max_readers);
+ if(!this->m_first_gate.timed_wait(lck, abs_time)){
+ if((this->m_ctrl.exclusive_in
+ || this->m_ctrl.upgradable_in
+ || this->m_ctrl.num_upr_shar == constants::max_readers)){
+ return false;
+ }
+ break;
}
}
@@ -433,7 +441,7 @@ inline bool interprocess_upgradable_mutex::timed_lock_upgradable
inline void interprocess_upgradable_mutex::unlock_upgradable()
{
- scoped_lock_t lock(m_mut);
+ scoped_lock_t lck(m_mut);
//Mark that upgradable lock has been acquired
//And add upgradable to the sharable count
this->m_ctrl.upgradable_in = 0;
@@ -445,14 +453,14 @@ inline void interprocess_upgradable_mutex::unlock_upgradable()
inline void interprocess_upgradable_mutex::lock_sharable()
{
- scoped_lock_t lock(m_mut);
+ scoped_lock_t lck(m_mut);
//The sharable lock must block in the first gate
//if an exclusive lock has been acquired
//or there are too many sharable locks
while(this->m_ctrl.exclusive_in
|| this->m_ctrl.num_upr_shar == constants::max_readers){
- this->m_first_gate.wait(lock);
+ this->m_first_gate.wait(lck);
}
//Increment sharable count
@@ -461,12 +469,12 @@ inline void interprocess_upgradable_mutex::lock_sharable()
inline bool interprocess_upgradable_mutex::try_lock_sharable()
{
- scoped_lock_t lock(m_mut, try_to_lock);
+ scoped_lock_t lck(m_mut, try_to_lock);
//The sharable lock must fail
//if an exclusive lock has been acquired
//or there are too many sharable locks
- if(!lock.owns()
+ if(!lck.owns()
|| this->m_ctrl.exclusive_in
|| this->m_ctrl.num_upr_shar == constants::max_readers){
return false;
@@ -480,21 +488,22 @@ inline bool interprocess_upgradable_mutex::try_lock_sharable()
inline bool interprocess_upgradable_mutex::timed_lock_sharable
(const boost::posix_time::ptime &abs_time)
{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock_sharable();
- return true;
- }
- scoped_lock_t lock(m_mut, abs_time);
- if(!lock.owns()) return false;
+ //Mutexes and condvars handle just fine infinite abs_times
+ //so avoid checking it here
+ scoped_lock_t lck(m_mut, abs_time);
+ if(!lck.owns()) return false;
//The sharable lock must block in the first gate
//if an exclusive lock has been acquired
//or there are too many sharable locks
while (this->m_ctrl.exclusive_in
|| this->m_ctrl.num_upr_shar == constants::max_readers){
- if(!this->m_first_gate.timed_wait(lock, abs_time)){
- return!(this->m_ctrl.exclusive_in
- || this->m_ctrl.num_upr_shar == constants::max_readers);
+ if(!this->m_first_gate.timed_wait(lck, abs_time)){
+ if(this->m_ctrl.exclusive_in
+ || this->m_ctrl.num_upr_shar == constants::max_readers){
+ return false;
+ }
+ break;
}
}
@@ -505,7 +514,7 @@ inline bool interprocess_upgradable_mutex::timed_lock_sharable
inline void interprocess_upgradable_mutex::unlock_sharable()
{
- scoped_lock_t lock(m_mut);
+ scoped_lock_t lck(m_mut);
//Decrement sharable count
--this->m_ctrl.num_upr_shar;
if (this->m_ctrl.num_upr_shar == 0){
@@ -522,7 +531,7 @@ inline void interprocess_upgradable_mutex::unlock_sharable()
inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable()
{
- scoped_lock_t lock(m_mut);
+ scoped_lock_t lck(m_mut);
//Unmark it as exclusive
this->m_ctrl.exclusive_in = 0;
//Mark it as upgradable
@@ -535,7 +544,7 @@ inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable()
inline void interprocess_upgradable_mutex::unlock_and_lock_sharable()
{
- scoped_lock_t lock(m_mut);
+ scoped_lock_t lck(m_mut);
//Unmark it as exclusive
this->m_ctrl.exclusive_in = 0;
//The sharable count should be 0 so increment it
@@ -546,7 +555,7 @@ inline void interprocess_upgradable_mutex::unlock_and_lock_sharable()
inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable()
{
- scoped_lock_t lock(m_mut);
+ scoped_lock_t lck(m_mut);
//Unmark it as upgradable (we don't have to decrement count)
this->m_ctrl.upgradable_in = 0;
//Notify readers/upgradable that they can enter
@@ -557,11 +566,11 @@ inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable()
inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock()
{
- scoped_lock_t lock(m_mut);
+ scoped_lock_t lck(m_mut);
//Simulate unlock_upgradable() without
//notifying sharables.
this->m_ctrl.upgradable_in = 0;
- --this->m_ctrl.num_upr_shar;
+ --this->m_ctrl.num_upr_shar;
//Execute the second half of exclusive locking
this->m_ctrl.exclusive_in = 1;
@@ -569,22 +578,22 @@ inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock()
upgradable_to_exclusive_rollback rollback(m_ctrl);
while (this->m_ctrl.num_upr_shar){
- this->m_second_gate.wait(lock);
+ this->m_second_gate.wait(lck);
}
rollback.release();
}
inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock()
{
- scoped_lock_t lock(m_mut, try_to_lock);
+ scoped_lock_t lck(m_mut, try_to_lock);
//Check if there are no readers
- if(!lock.owns()
+ if(!lck.owns()
|| this->m_ctrl.num_upr_shar != 1){
return false;
}
//Now unlock upgradable and mark exclusive
this->m_ctrl.upgradable_in = 0;
- --this->m_ctrl.num_upr_shar;
+ --this->m_ctrl.num_upr_shar;
this->m_ctrl.exclusive_in = 1;
return true;
}
@@ -592,13 +601,15 @@ inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock()
inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock
(const boost::posix_time::ptime &abs_time)
{
- scoped_lock_t lock(m_mut, abs_time);
- if(!lock.owns()) return false;
+ //Mutexes and condvars handle just fine infinite abs_times
+ //so avoid checking it here
+ scoped_lock_t lck(m_mut, abs_time);
+ if(!lck.owns()) return false;
//Simulate unlock_upgradable() without
//notifying sharables.
this->m_ctrl.upgradable_in = 0;
- --this->m_ctrl.num_upr_shar;
+ --this->m_ctrl.num_upr_shar;
//Execute the second half of exclusive locking
this->m_ctrl.exclusive_in = 1;
@@ -606,8 +617,11 @@ inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock
upgradable_to_exclusive_rollback rollback(m_ctrl);
while (this->m_ctrl.num_upr_shar){
- if(!this->m_second_gate.timed_wait(lock, abs_time)){
- return !(this->m_ctrl.num_upr_shar);
+ if(!this->m_second_gate.timed_wait(lck, abs_time)){
+ if(this->m_ctrl.num_upr_shar){
+ return false;
+ }
+ break;
}
}
rollback.release();
@@ -616,11 +630,11 @@ inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock
inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock()
{
- scoped_lock_t lock(m_mut, try_to_lock);
+ scoped_lock_t lck(m_mut, try_to_lock);
//If we can't lock or any has there is any exclusive, upgradable
//or sharable mark return false;
- if(!lock.owns()
+ if(!lck.owns()
|| this->m_ctrl.exclusive_in
|| this->m_ctrl.upgradable_in
|| this->m_ctrl.num_upr_shar != 1){
@@ -633,11 +647,11 @@ inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock()
inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
{
- scoped_lock_t lock(m_mut, try_to_lock);
+ scoped_lock_t lck(m_mut, try_to_lock);
//The upgradable lock must fail
//if an exclusive or upgradable lock has been acquired
- if(!lock.owns()
+ if(!lck.owns()
|| this->m_ctrl.exclusive_in
|| this->m_ctrl.upgradable_in){
return false;
@@ -648,7 +662,7 @@ inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradab
return true;
}
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/sync/lock_options.hpp b/boost/interprocess/sync/lock_options.hpp
index 74f3399a4c..7e3305ba44 100644
--- a/boost/interprocess/sync/lock_options.hpp
+++ b/boost/interprocess/sync/lock_options.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_LOCK_OPTIONS_HPP
#define BOOST_INTERPROCESS_LOCK_OPTIONS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -23,9 +23,13 @@
namespace boost {
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
namespace posix_time
{ class ptime; }
+#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
namespace interprocess {
//!Type to indicate to a mutex lock constructor that must not lock the mutex.
diff --git a/boost/interprocess/sync/mutex_family.hpp b/boost/interprocess/sync/mutex_family.hpp
index b153ffea3e..f19805f1b2 100644
--- a/boost/interprocess/sync/mutex_family.hpp
+++ b/boost/interprocess/sync/mutex_family.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_MUTEX_FAMILY_HPP
#define BOOST_INTERPROCESS_MUTEX_FAMILY_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/sync/named_condition.hpp b/boost/interprocess/sync/named_condition.hpp
index ca0205ad73..4f0d61e253 100644
--- a/boost/interprocess/sync/named_condition.hpp
+++ b/boost/interprocess/sync/named_condition.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_NAMED_CONDITION_HPP
#define BOOST_INTERPROCESS_NAMED_CONDITION_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -22,6 +22,7 @@
#include <boost/interprocess/detail/interprocess_tester.hpp>
#include <boost/interprocess/permissions.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/detail/locks.hpp>
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
#include <boost/interprocess/sync/windows/named_condition.hpp>
#define BOOST_INTERPROCESS_USE_WINDOWS
@@ -35,21 +36,21 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail{ class interprocess_tester; }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//! A global condition variable that can be created by name.
//! This condition variable is designed to work with named_mutex and
//! can't be placed in shared memory or memory mapped files.
class named_condition
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
named_condition();
named_condition(const named_condition &);
named_condition &operator=(const named_condition &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Creates a global condition with a name.
//!If the condition can't be created throws interprocess_exception
@@ -113,7 +114,7 @@ class named_condition
//!Returns false on error. Never throws.
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
#if defined(BOOST_INTERPROCESS_USE_WINDOWS)
typedef ipcdetail::windows_named_condition condition_type;
@@ -125,10 +126,10 @@ class named_condition
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction()
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); }
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_condition::~named_condition()
{}
@@ -153,26 +154,40 @@ inline void named_condition::notify_all()
template <typename L>
inline void named_condition::wait(L& lock)
-{ m_cond.wait(lock); }
+{
+ ipcdetail::internal_mutex_lock<L> internal_lock(lock);
+ m_cond.wait(internal_lock);
+}
template <typename L, typename Pr>
inline void named_condition::wait(L& lock, Pr pred)
-{ m_cond.wait(lock, pred); }
+{
+ ipcdetail::internal_mutex_lock<L> internal_lock(lock);
+ m_cond.wait(internal_lock, pred);
+}
template <typename L>
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time)
-{ return m_cond.timed_wait(lock, abs_time); }
+{
+ ipcdetail::internal_mutex_lock<L> internal_lock(lock);
+ return m_cond.timed_wait(internal_lock, abs_time);
+}
template <typename L, typename Pr>
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
-{ return m_cond.timed_wait(lock, abs_time, pred); }
+{
+ ipcdetail::internal_mutex_lock<L> internal_lock(lock);
+ return m_cond.timed_wait(internal_lock, abs_time, pred);
+}
inline bool named_condition::remove(const char *name)
-{ return condition_type::remove(name); }
+{
+ return condition_type::remove(name);
+}
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess
} //namespace boost
diff --git a/boost/interprocess/sync/named_condition_any.hpp b/boost/interprocess/sync/named_condition_any.hpp
new file mode 100644
index 0000000000..5d99d22ddd
--- /dev/null
+++ b/boost/interprocess/sync/named_condition_any.hpp
@@ -0,0 +1,151 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP
+#define BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/detail/locks.hpp>
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+ #include <boost/interprocess/sync/windows/named_condition_any.hpp>
+ #define BOOST_INTERPROCESS_USE_WINDOWS
+#else
+ #include <boost/interprocess/sync/shm/named_condition_any.hpp>
+#endif
+
+//!\file
+//!Describes a named condition class for inter-process synchronization
+
+namespace boost {
+namespace interprocess {
+
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+namespace ipcdetail{ class interprocess_tester; }
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//! A global condition variable that can be created by name.
+//! This condition variable is designed to work with named_mutex and
+//! can't be placed in shared memory or memory mapped files.
+class named_condition_any
+{
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ //Non-copyable
+ named_condition_any();
+ named_condition_any(const named_condition_any &);
+ named_condition_any &operator=(const named_condition_any &);
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ public:
+ //!Creates a global condition with a name.
+ //!If the condition can't be created throws interprocess_exception
+ named_condition_any(create_only_t, const char *name, const permissions &perm = permissions())
+ : m_cond(create_only_t(), name, perm)
+ {}
+
+ //!Opens or creates a global condition with a name.
+ //!If the condition is created, this call is equivalent to
+ //!named_condition_any(create_only_t, ... )
+ //!If the condition is already created, this call is equivalent
+ //!named_condition_any(open_only_t, ... )
+ //!Does not throw
+ named_condition_any(open_or_create_t, const char *name, const permissions &perm = permissions())
+ : m_cond(open_or_create_t(), name, perm)
+ {}
+
+ //!Opens a global condition with a name if that condition is previously
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ named_condition_any(open_only_t, const char *name)
+ : m_cond(open_only_t(), name)
+ {}
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~named_condition_any()
+ {}
+
+ //!If there is a thread waiting on *this, change that
+ //!thread's state to ready. Otherwise there is no effect.*/
+ void notify_one()
+ { m_cond.notify_one(); }
+
+ //!Change the state of all threads waiting on *this to ready.
+ //!If there are no waiting threads, notify_all() has no effect.
+ void notify_all()
+ { m_cond.notify_all(); }
+
+ //!Releases the lock on the named_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), and then reacquires the lock.
+ template <typename L>
+ void wait(L& lock)
+ { return m_cond.wait(lock); }
+
+ //!The same as:
+ //!while (!pred()) wait(lock)
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ { return m_cond.wait(lock, pred); }
+
+ //!Releases the lock on the named_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
+ //!and then reacquires the lock.
+ //!Returns: false if time abs_time is reached, otherwise true.
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ { return m_cond.timed_wait(lock, abs_time); }
+
+ //!The same as: while (!pred()) {
+ //! if (!timed_wait(lock, abs_time)) return pred();
+ //! } return true;
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ { return m_cond.timed_wait(lock, abs_time, pred); }
+
+ //!Erases a named condition from the system.
+ //!Returns false on error. Never throws.
+ static bool remove(const char *name)
+ { return condition_any_type::remove(name); }
+
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ private:
+ #if defined(BOOST_INTERPROCESS_USE_WINDOWS)
+ typedef ipcdetail::windows_named_condition_any condition_any_type;
+ #else
+ typedef ipcdetail::shm_named_condition_any condition_any_type;
+ #endif
+ condition_any_type m_cond;
+
+ friend class ipcdetail::interprocess_tester;
+ void dont_close_on_destruction()
+ { ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); }
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+};
+
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP
diff --git a/boost/interprocess/sync/named_mutex.hpp b/boost/interprocess/sync/named_mutex.hpp
index c34193c697..e91b1f4d8f 100644
--- a/boost/interprocess/sync/named_mutex.hpp
+++ b/boost/interprocess/sync/named_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_NAMED_MUTEX_HPP
#define BOOST_INTERPROCESS_NAMED_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -46,17 +46,17 @@ class named_condition;
//!each process should have it's own named_mutex.
class named_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
named_mutex();
named_mutex(const named_mutex &);
named_mutex &operator=(const named_mutex &);
friend class named_condition;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
- //!Creates a global interprocess_mutex with a name.
+ //!Creates a global mutex with a name.
//!Throws interprocess_exception on error.
named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
@@ -82,19 +82,19 @@ class named_mutex
~named_mutex();
//!Unlocks a previously locked
- //!interprocess_mutex.
+ //!mutex.
void unlock();
- //!Locks interprocess_mutex, sleeps when interprocess_mutex is already locked.
+ //!Locks the mutex, sleeps when the mutex is already locked.
//!Throws interprocess_exception if a severe error is found
void lock();
- //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex
+ //!Tries to lock the mutex, returns false when the mutex
//!is already locked, returns true when success.
//!Throws interprocess_exception if a severe error is found
bool try_lock();
- //!Tries to lock the interprocess_mutex until time abs_time,
+ //!Tries to lock the the mutex until time abs_time,
//!Returns false when timeout expires, returns true when locks.
//!Throws interprocess_exception if a severe error is found
bool timed_lock(const boost::posix_time::ptime &abs_time);
@@ -103,31 +103,30 @@ class named_mutex
//!Returns false on error. Never throws.
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction();
+ public:
#if defined(BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES)
- typedef ipcdetail::posix_named_mutex impl_t;
- impl_t m_mut;
+ typedef ipcdetail::posix_named_mutex internal_mutex_type;
#undef BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES
#elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
- typedef ipcdetail::windows_named_mutex impl_t;
- impl_t m_mut;
+ typedef ipcdetail::windows_named_mutex internal_mutex_type;
#undef BOOST_INTERPROCESS_USE_WINDOWS
#else
- typedef ipcdetail::shm_named_mutex impl_t;
- impl_t m_mut;
- public:
- interprocess_mutex *mutex() const
- { return m_mut.mutex(); }
+ typedef ipcdetail::shm_named_mutex internal_mutex_type;
#endif
+ internal_mutex_type &internal_mutex()
+ { return m_mut; }
+
+ internal_mutex_type m_mut;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_mutex::named_mutex(create_only_t, const char *name, const permissions &perm)
: m_mut(create_only_t(), name, perm)
@@ -160,9 +159,9 @@ inline bool named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{ return m_mut.timed_lock(abs_time); }
inline bool named_mutex::remove(const char *name)
-{ return impl_t::remove(name); }
+{ return internal_mutex_type::remove(name); }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/sync/named_recursive_mutex.hpp b/boost/interprocess/sync/named_recursive_mutex.hpp
index 2d4b9b2416..f1f629dfcb 100644
--- a/boost/interprocess/sync/named_recursive_mutex.hpp
+++ b/boost/interprocess/sync/named_recursive_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP
#define BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -33,21 +33,21 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail{ class interprocess_tester; }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!A recursive mutex with a global name, so it can be found from different
//!processes. This mutex can't be placed in shared memory, and
//!each process should have it's own named_recursive_mutex.
class named_recursive_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
named_recursive_mutex();
named_recursive_mutex(const named_recursive_mutex &);
named_recursive_mutex &operator=(const named_recursive_mutex &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Creates a global recursive_mutex with a name.
@@ -97,7 +97,7 @@ class named_recursive_mutex
//!from the system
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction();
@@ -110,10 +110,10 @@ class named_recursive_mutex
#endif
impl_t m_mut;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_recursive_mutex::~named_recursive_mutex()
{}
@@ -143,18 +143,12 @@ inline bool named_recursive_mutex::try_lock()
{ return m_mut.try_lock(); }
inline bool named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
- return m_mut.timed_lock(abs_time);
-}
+{ return m_mut.timed_lock(abs_time); }
inline bool named_recursive_mutex::remove(const char *name)
{ return impl_t::remove(name); }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/sync/named_semaphore.hpp b/boost/interprocess/sync/named_semaphore.hpp
index 39c9096fb6..c4a421ec2b 100644
--- a/boost/interprocess/sync/named_semaphore.hpp
+++ b/boost/interprocess/sync/named_semaphore.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP
#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -44,13 +44,13 @@ namespace interprocess {
//!acknowledgment mechanisms.
class named_semaphore
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
named_semaphore();
named_semaphore(const named_semaphore &);
named_semaphore &operator=(const named_semaphore &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Creates a global semaphore with a name, and an initial count.
@@ -104,7 +104,7 @@ class named_semaphore
//!Returns false on error. Never throws.
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction();
@@ -118,10 +118,10 @@ class named_semaphore
typedef ipcdetail::shm_named_semaphore impl_t;
#endif
impl_t m_sem;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_semaphore::named_semaphore
(create_only_t, const char *name, unsigned int initialCount, const permissions &perm)
@@ -153,18 +153,12 @@ inline bool named_semaphore::try_wait()
{ return m_sem.try_wait(); }
inline bool named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait();
- return true;
- }
- return m_sem.timed_wait(abs_time);
-}
+{ return m_sem.timed_wait(abs_time); }
inline bool named_semaphore::remove(const char *name)
{ return impl_t::remove(name); }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/sync/named_sharable_mutex.hpp b/boost/interprocess/sync/named_sharable_mutex.hpp
new file mode 100644
index 0000000000..f4c0aaaee9
--- /dev/null
+++ b/boost/interprocess/sync/named_sharable_mutex.hpp
@@ -0,0 +1,230 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP
+#define BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/sync/interprocess_sharable_mutex.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+//!\file
+//!Describes a named sharable mutex class for inter-process synchronization
+
+namespace boost {
+namespace interprocess {
+
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+namespace ipcdetail{ class interprocess_tester; }
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+class named_condition;
+
+//!A sharable mutex with a global name, so it can be found from different
+//!processes. This mutex can't be placed in shared memory, and
+//!each process should have it's own named sharable mutex.
+class named_sharable_mutex
+{
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ //Non-copyable
+ named_sharable_mutex();
+ named_sharable_mutex(const named_sharable_mutex &);
+ named_sharable_mutex &operator=(const named_sharable_mutex &);
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ public:
+
+ //!Creates a global sharable mutex with a name.
+ //!If the sharable mutex can't be created throws interprocess_exception
+ named_sharable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
+
+ //!Opens or creates a global sharable mutex with a name.
+ //!If the sharable mutex is created, this call is equivalent to
+ //!named_sharable_mutex(create_only_t, ...)
+ //!If the sharable mutex is already created, this call is equivalent to
+ //!named_sharable_mutex(open_only_t, ... ).
+ named_sharable_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
+
+ //!Opens a global sharable mutex with a name if that sharable mutex
+ //!is previously.
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ named_sharable_mutex(open_only_t open_only, const char *name);
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~named_sharable_mutex();
+
+ //Exclusive locking
+
+ //!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
+ //! and if another thread has exclusive or sharable ownership of
+ //! the mutex, it waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! without waiting. If no other thread has exclusive or sharable
+ //! ownership of the mutex this succeeds.
+ //!Returns: If it can acquire exclusive ownership immediately returns true.
+ //! If it has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive, or sharable
+ //! ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The calling thread releases the exclusive ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock();
+
+ //Sharable locking
+
+ //!Effects: The calling thread tries to obtain sharable ownership of the mutex,
+ //! and if another thread has exclusive ownership of the mutex,
+ //! waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! without waiting. If no other thread has exclusive ownership
+ //! of the mutex this succeeds.
+ //!Returns: If it can acquire sharable ownership immediately returns true. If it
+ //! has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive
+ //! ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have sharable ownership of the mutex.
+ //!Effects: The calling thread releases the sharable ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_sharable();
+
+ //!Erases a named sharable mutex from the system.
+ //!Returns false on error. Never throws.
+ static bool remove(const char *name);
+
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ private:
+ friend class ipcdetail::interprocess_tester;
+ void dont_close_on_destruction();
+
+ interprocess_sharable_mutex *mutex() const
+ { return static_cast<interprocess_sharable_mutex*>(m_shmem.get_user_address()); }
+
+ typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
+ open_create_impl_t m_shmem;
+ typedef ipcdetail::named_creation_functor<interprocess_sharable_mutex> construct_func_t;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+};
+
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+inline named_sharable_mutex::~named_sharable_mutex()
+{}
+
+inline named_sharable_mutex::named_sharable_mutex
+ (create_only_t, const char *name, const permissions &perm)
+ : m_shmem (create_only
+ ,name
+ ,sizeof(interprocess_sharable_mutex) +
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoCreate)
+ ,perm)
+{}
+
+inline named_sharable_mutex::named_sharable_mutex
+ (open_or_create_t, const char *name, const permissions &perm)
+ : m_shmem (open_or_create
+ ,name
+ ,sizeof(interprocess_sharable_mutex) +
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoOpenOrCreate)
+ ,perm)
+{}
+
+inline named_sharable_mutex::named_sharable_mutex
+ (open_only_t, const char *name)
+ : m_shmem (open_only
+ ,name
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoOpen))
+{}
+
+inline void named_sharable_mutex::dont_close_on_destruction()
+{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); }
+
+inline void named_sharable_mutex::lock()
+{ this->mutex()->lock(); }
+
+inline void named_sharable_mutex::unlock()
+{ this->mutex()->unlock(); }
+
+inline bool named_sharable_mutex::try_lock()
+{ return this->mutex()->try_lock(); }
+
+inline bool named_sharable_mutex::timed_lock
+ (const boost::posix_time::ptime &abs_time)
+{ return this->mutex()->timed_lock(abs_time); }
+
+inline void named_sharable_mutex::lock_sharable()
+{ this->mutex()->lock_sharable(); }
+
+inline void named_sharable_mutex::unlock_sharable()
+{ this->mutex()->unlock_sharable(); }
+
+inline bool named_sharable_mutex::try_lock_sharable()
+{ return this->mutex()->try_lock_sharable(); }
+
+inline bool named_sharable_mutex::timed_lock_sharable
+ (const boost::posix_time::ptime &abs_time)
+{ return this->mutex()->timed_lock_sharable(abs_time); }
+
+inline bool named_sharable_mutex::remove(const char *name)
+{ return shared_memory_object::remove(name); }
+
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP
diff --git a/boost/interprocess/sync/named_upgradable_mutex.hpp b/boost/interprocess/sync/named_upgradable_mutex.hpp
index c45fd08270..e313e72ed4 100644
--- a/boost/interprocess/sync/named_upgradable_mutex.hpp
+++ b/boost/interprocess/sync/named_upgradable_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_named_upgradable_mutex_HPP
#define BOOST_INTERPROCESS_named_upgradable_mutex_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -32,9 +32,9 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail{ class interprocess_tester; }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
class named_condition;
@@ -43,20 +43,20 @@ class named_condition;
//!each process should have it's own named upgradable mutex.
class named_upgradable_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
named_upgradable_mutex();
named_upgradable_mutex(const named_upgradable_mutex &);
named_upgradable_mutex &operator=(const named_upgradable_mutex &);
friend class named_condition;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Creates a global upgradable mutex with a name.
//!If the upgradable mutex can't be created throws interprocess_exception
named_upgradable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
- //!Opens or creates a global upgradable mutex with a name, and an initial count.
+ //!Opens or creates a global upgradable mutex with a name.
//!If the upgradable mutex is created, this call is equivalent to
//!named_upgradable_mutex(create_only_t, ...)
//!If the upgradable mutex is already created, this call is equivalent to
@@ -215,13 +215,19 @@ class named_upgradable_mutex
//!Throws: An exception derived from interprocess_exception on error.
bool try_unlock_sharable_and_lock();
+ //!Precondition: The thread must have sharable ownership of the mutex.
+ //!Effects: The thread atomically releases sharable ownership and tries to acquire
+ //! upgradable ownership. This operation will fail if there are threads with sharable
+ //! or upgradable ownership, but it will maintain sharable ownership.
+ //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
+ //!Throws: An exception derived from interprocess_exception on error.
bool try_unlock_sharable_and_lock_upgradable();
//!Erases a named upgradable mutex from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction();
@@ -229,12 +235,13 @@ class named_upgradable_mutex
interprocess_upgradable_mutex *mutex() const
{ return static_cast<interprocess_upgradable_mutex*>(m_shmem.get_user_address()); }
- ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
+ open_create_impl_t m_shmem;
typedef ipcdetail::named_creation_functor<interprocess_upgradable_mutex> construct_func_t;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_upgradable_mutex::~named_upgradable_mutex()
{}
@@ -244,8 +251,7 @@ inline named_upgradable_mutex::named_upgradable_mutex
: m_shmem (create_only
,name
,sizeof(interprocess_upgradable_mutex) +
- ipcdetail::managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoCreate)
@@ -257,8 +263,7 @@ inline named_upgradable_mutex::named_upgradable_mutex
: m_shmem (open_or_create
,name
,sizeof(interprocess_upgradable_mutex) +
- ipcdetail::managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoOpenOrCreate)
@@ -288,13 +293,7 @@ inline bool named_upgradable_mutex::try_lock()
inline bool named_upgradable_mutex::timed_lock
(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
- return this->mutex()->timed_lock(abs_time);
-}
+{ return this->mutex()->timed_lock(abs_time); }
inline void named_upgradable_mutex::lock_upgradable()
{ this->mutex()->lock_upgradable(); }
@@ -307,13 +306,7 @@ inline bool named_upgradable_mutex::try_lock_upgradable()
inline bool named_upgradable_mutex::timed_lock_upgradable
(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock_upgradable();
- return true;
- }
- return this->mutex()->timed_lock_upgradable(abs_time);
-}
+{ return this->mutex()->timed_lock_upgradable(abs_time); }
inline void named_upgradable_mutex::lock_sharable()
{ this->mutex()->lock_sharable(); }
@@ -326,13 +319,7 @@ inline bool named_upgradable_mutex::try_lock_sharable()
inline bool named_upgradable_mutex::timed_lock_sharable
(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock_sharable();
- return true;
- }
- return this->mutex()->timed_lock_sharable(abs_time);
-}
+{ return this->mutex()->timed_lock_sharable(abs_time); }
inline void named_upgradable_mutex::unlock_and_lock_upgradable()
{ this->mutex()->unlock_and_lock_upgradable(); }
@@ -362,7 +349,7 @@ inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
inline bool named_upgradable_mutex::remove(const char *name)
{ return shared_memory_object::remove(name); }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/sync/null_mutex.hpp b/boost/interprocess/sync/null_mutex.hpp
index afe444ed3f..16db64b8d2 100644
--- a/boost/interprocess/sync/null_mutex.hpp
+++ b/boost/interprocess/sync/null_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_NULL_MUTEX_HPP
#define BOOST_INTERPROCESS_NULL_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -24,19 +24,23 @@
namespace boost {
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
namespace posix_time
{ class ptime; }
+#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
namespace interprocess {
//!Implements a mutex that simulates a mutex without doing any operation and
//!simulates a successful operation.
class null_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
null_mutex(const null_mutex&);
null_mutex &operator= (const null_mutex&);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Constructor.
diff --git a/boost/interprocess/sync/posix/condition.hpp b/boost/interprocess/sync/posix/condition.hpp
index 48be099f60..e09fe4a109 100644
--- a/boost/interprocess/sync/posix/condition.hpp
+++ b/boost/interprocess/sync/posix/condition.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_POSIX_CONDITION_HPP
#define BOOST_INTERPROCESS_POSIX_CONDITION_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -19,7 +19,7 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <pthread.h>
-#include <errno.h>
+#include <errno.h>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
@@ -83,12 +83,13 @@ class posix_condition
template <typename L>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
{
+ if (!lock)
+ throw lock_exception();
+ //Posix does not support infinity absolute time so handle it here
if(abs_time == boost::posix_time::pos_infin){
this->wait(lock);
return true;
}
- if (!lock)
- throw lock_exception();
return this->do_timed_wait(abs_time, *lock.mutex());
}
@@ -98,17 +99,17 @@ class posix_condition
template <typename L, typename Pr>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
{
+ if (!lock)
+ throw lock_exception();
+ //Posix does not support infinity absolute time so handle it here
if(abs_time == boost::posix_time::pos_infin){
this->wait(lock, pred);
return true;
}
- if (!lock)
- throw lock_exception();
while (!pred()){
if (!this->do_timed_wait(abs_time, *lock.mutex()))
return pred();
}
-
return true;
}
@@ -145,21 +146,21 @@ inline posix_condition::~posix_condition()
{
int res = 0;
res = pthread_cond_destroy(&m_condition);
- BOOST_ASSERT(res == 0);
+ BOOST_ASSERT(res == 0); (void)res;
}
inline void posix_condition::notify_one()
{
int res = 0;
res = pthread_cond_signal(&m_condition);
- BOOST_ASSERT(res == 0);
+ BOOST_ASSERT(res == 0); (void)res;
}
inline void posix_condition::notify_all()
{
int res = 0;
res = pthread_cond_broadcast(&m_condition);
- BOOST_ASSERT(res == 0);
+ BOOST_ASSERT(res == 0); (void)res;
}
inline void posix_condition::do_wait(posix_mutex &mut)
@@ -167,7 +168,7 @@ inline void posix_condition::do_wait(posix_mutex &mut)
pthread_mutex_t* pmutex = &mut.m_mut;
int res = 0;
res = pthread_cond_wait(&m_condition, pmutex);
- BOOST_ASSERT(res == 0);
+ BOOST_ASSERT(res == 0); (void)res;
}
inline bool posix_condition::do_timed_wait
diff --git a/boost/interprocess/sync/posix/mutex.hpp b/boost/interprocess/sync/posix/mutex.hpp
index 393807c97a..4cd4207061 100644
--- a/boost/interprocess/sync/posix/mutex.hpp
+++ b/boost/interprocess/sync/posix/mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -27,7 +27,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP
#define BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -35,7 +35,7 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <pthread.h>
-#include <errno.h>
+#include <errno.h>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
@@ -44,6 +44,7 @@
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
# include <boost/interprocess/detail/os_thread_functions.hpp>
+# include <boost/interprocess/sync/detail/common_algorithms.hpp>
#endif
#include <boost/assert.hpp>
@@ -102,12 +103,12 @@ inline bool posix_mutex::try_lock()
inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
+ #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+ //Posix does not support infinity absolute time so handle it here
if(abs_time == boost::posix_time::pos_infin){
this->lock();
return true;
}
- #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
-
timespec ts = ptime_to_timespec(abs_time);
int res = pthread_mutex_timedlock(&m_mut, &ts);
if (res != 0 && res != ETIMEDOUT)
@@ -116,22 +117,7 @@ inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
#else //BOOST_INTERPROCESS_POSIX_TIMEOUTS
- //Obtain current count and target time
- boost::posix_time::ptime now = microsec_clock::universal_time();
-
- do{
- if(this->try_lock()){
- break;
- }
- now = microsec_clock::universal_time();
-
- if(now >= abs_time){
- return false;
- }
- // relinquish current time slice
- thread_yield();
- }while (true);
- return true;
+ return ipcdetail::try_based_timed_lock(*this, abs_time);
#endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS
}
@@ -140,6 +126,7 @@ inline void posix_mutex::unlock()
{
int res = 0;
res = pthread_mutex_unlock(&m_mut);
+ (void)res;
BOOST_ASSERT(res == 0);
}
diff --git a/boost/interprocess/sync/posix/named_mutex.hpp b/boost/interprocess/sync/posix/named_mutex.hpp
index 931c731eff..2b3be2f8be 100644
--- a/boost/interprocess/sync/posix/named_mutex.hpp
+++ b/boost/interprocess/sync/posix/named_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP
#define BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -32,13 +32,13 @@ class named_condition;
class posix_named_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
posix_named_mutex();
posix_named_mutex(const posix_named_mutex &);
posix_named_mutex &operator=(const posix_named_mutex &);
friend class named_condition;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
posix_named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
@@ -55,16 +55,16 @@ class posix_named_mutex
bool timed_lock(const boost::posix_time::ptime &abs_time);
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class interprocess_tester;
void dont_close_on_destruction();
posix_named_semaphore m_sem;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline posix_named_mutex::posix_named_mutex(create_only_t, const char *name, const permissions &perm)
: m_sem(create_only, name, 1, perm)
@@ -94,18 +94,12 @@ inline bool posix_named_mutex::try_lock()
{ return m_sem.try_wait(); }
inline bool posix_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
- return m_sem.timed_wait(abs_time);
-}
+{ return m_sem.timed_wait(abs_time); }
inline bool posix_named_mutex::remove(const char *name)
{ return posix_named_semaphore::remove(name); }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace ipcdetail {
} //namespace interprocess {
diff --git a/boost/interprocess/sync/posix/named_semaphore.hpp b/boost/interprocess/sync/posix/named_semaphore.hpp
index f0327a4618..03510e3baa 100644
--- a/boost/interprocess/sync/posix/named_semaphore.hpp
+++ b/boost/interprocess/sync/posix/named_semaphore.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP
#define BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -23,9 +23,9 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail{ class interprocess_tester; }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
namespace ipcdetail {
diff --git a/boost/interprocess/sync/posix/pthread_helpers.hpp b/boost/interprocess/sync/posix/pthread_helpers.hpp
index bcbc44be33..ce859d7918 100644
--- a/boost/interprocess/sync/posix/pthread_helpers.hpp
+++ b/boost/interprocess/sync/posix/pthread_helpers.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP
#define BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -19,8 +19,8 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <pthread.h>
-#include <errno.h>
-#include <boost/interprocess/exceptions.hpp>
+#include <errno.h>
+#include <boost/interprocess/exceptions.hpp>
namespace boost {
namespace interprocess {
@@ -86,7 +86,7 @@ namespace ipcdetail{
void release() {mp_mut = 0; }
- private:
+ private:
pthread_mutex_t *mp_mut;
};
@@ -105,7 +105,7 @@ namespace ipcdetail{
void release() { mp_cond = 0; }
- private:
+ private:
pthread_cond_t *mp_cond;
};
@@ -151,7 +151,7 @@ namespace ipcdetail{
void release() {mp_barrier = 0; }
- private:
+ private:
pthread_barrier_t *mp_barrier;
};
diff --git a/boost/interprocess/sync/posix/ptime_to_timespec.hpp b/boost/interprocess/sync/posix/ptime_to_timespec.hpp
index 7d787353bd..65993de958 100644
--- a/boost/interprocess/sync/posix/ptime_to_timespec.hpp
+++ b/boost/interprocess/sync/posix/ptime_to_timespec.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP
#define BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
namespace boost {
@@ -22,7 +26,9 @@ namespace ipcdetail {
inline timespec ptime_to_timespec (const boost::posix_time::ptime &tm)
{
const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
- boost::posix_time::time_duration duration (tm - epoch);
+ //Avoid negative absolute times
+ boost::posix_time::time_duration duration = (tm <= epoch) ? boost::posix_time::time_duration(epoch - epoch)
+ : boost::posix_time::time_duration(tm - epoch);
timespec ts;
ts.tv_sec = duration.total_seconds();
ts.tv_nsec = duration.total_nanoseconds() % 1000000000;
diff --git a/boost/interprocess/sync/posix/recursive_mutex.hpp b/boost/interprocess/sync/posix/recursive_mutex.hpp
index 456c9a4874..ccb50da286 100644
--- a/boost/interprocess/sync/posix/recursive_mutex.hpp
+++ b/boost/interprocess/sync/posix/recursive_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -27,17 +27,22 @@
#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP
#define BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <pthread.h>
-#include <errno.h>
+#include <errno.h>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/exceptions.hpp>
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
# include <boost/interprocess/detail/os_thread_functions.hpp>
+# include <boost/interprocess/sync/detail/common_algorithms.hpp>
#endif
#include <boost/assert.hpp>
@@ -92,11 +97,12 @@ inline bool posix_recursive_mutex::try_lock()
inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
+ #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+ //Posix does not support infinity absolute time so handle it here
if(abs_time == boost::posix_time::pos_infin){
this->lock();
return true;
}
- #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
timespec ts = ptime_to_timespec(abs_time);
int res = pthread_mutex_timedlock(&m_mut, &ts);
@@ -106,22 +112,7 @@ inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &ab
#else //BOOST_INTERPROCESS_POSIX_TIMEOUTS
- //Obtain current count and target time
- boost::posix_time::ptime now = microsec_clock::universal_time();
-
- do{
- if(this->try_lock()){
- break;
- }
- now = microsec_clock::universal_time();
-
- if(now >= abs_time){
- return false;
- }
- // relinquish current time slice
- thread_yield();
- }while (true);
- return true;
+ return ipcdetail::try_based_timed_lock(*this, abs_time);
#endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS
}
@@ -130,7 +121,7 @@ inline void posix_recursive_mutex::unlock()
{
int res = 0;
res = pthread_mutex_unlock(&m_mut);
- BOOST_ASSERT(res == 0);
+ BOOST_ASSERT(res == 0); (void)res;
}
} //namespace ipcdetail {
diff --git a/boost/interprocess/sync/posix/semaphore.hpp b/boost/interprocess/sync/posix/semaphore.hpp
index b7f62cc42d..ba6a6f0eba 100644
--- a/boost/interprocess/sync/posix/semaphore.hpp
+++ b/boost/interprocess/sync/posix/semaphore.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP
#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/sync/posix/semaphore_wrapper.hpp b/boost/interprocess/sync/posix/semaphore_wrapper.hpp
index 22184cda9d..33f55fae54 100644
--- a/boost/interprocess/sync/posix/semaphore_wrapper.hpp
+++ b/boost/interprocess/sync/posix/semaphore_wrapper.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,11 +11,15 @@
#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
-#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/detail/shared_dir_helpers.hpp>
#include <boost/interprocess/permissions.hpp>
#include <fcntl.h> //O_CREAT, O_*...
@@ -35,6 +39,8 @@
#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
#else
#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/sync/detail/locks.hpp>
+#include <boost/interprocess/sync/detail/common_algorithms.hpp>
#endif
namespace boost {
@@ -49,7 +55,7 @@ inline bool semaphore_open
#ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
add_leading_slash(origname, name);
#else
- create_tmp_and_clean_old_and_get_filename(origname, name);
+ create_shared_dir_cleaning_old_and_get_filepath(origname, name);
#endif
//Create new mapping
@@ -103,7 +109,7 @@ inline bool semaphore_open
inline void semaphore_close(sem_t *handle)
{
int ret = sem_close(handle);
- if(ret != 0){
+ if(ret != 0){
BOOST_ASSERT(0);
}
}
@@ -115,7 +121,7 @@ inline bool semaphore_unlink(const char *semname)
#ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
add_leading_slash(semname, sem_str);
#else
- tmp_filename(semname, sem_str);
+ shared_filepath(semname, sem_str);
#endif
return 0 == sem_unlink(sem_str.c_str());
}
@@ -131,14 +137,15 @@ inline void semaphore_init(sem_t *handle, unsigned int initialCount)
//sem_init call is not defined, but -1 is returned on failure.
//In the future, a successful call might be required to return 0.
if(ret == -1){
- throw interprocess_exception(system_error_code());
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
}
}
inline void semaphore_destroy(sem_t *handle)
{
int ret = sem_destroy(handle);
- if(ret != 0){
+ if(ret != 0){
BOOST_ASSERT(0);
}
}
@@ -147,7 +154,8 @@ inline void semaphore_post(sem_t *handle)
{
int ret = sem_post(handle);
if(ret != 0){
- throw interprocess_exception(system_error_code());
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
}
}
@@ -155,7 +163,8 @@ inline void semaphore_wait(sem_t *handle)
{
int ret = sem_wait(handle);
if(ret != 0){
- throw interprocess_exception(system_error_code());
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
}
}
@@ -167,17 +176,39 @@ inline bool semaphore_try_wait(sem_t *handle)
if(system_error_code() == EAGAIN){
return false;
}
- throw interprocess_exception(system_error_code());
- return false;
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
}
+#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+
+struct semaphore_wrapper_try_wrapper
+{
+ explicit semaphore_wrapper_try_wrapper(sem_t *handle)
+ : m_handle(handle)
+ {}
+
+ void wait()
+ { semaphore_wait(m_handle); }
+
+ bool try_wait()
+ { return semaphore_try_wait(m_handle); }
+
+ private:
+ sem_t *m_handle;
+};
+
+#endif
+
inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time)
{
+ #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+ //Posix does not support infinity absolute time so handle it here
if(abs_time == boost::posix_time::pos_infin){
semaphore_wait(handle);
return true;
}
- #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+
timespec tspec = ptime_to_timespec(abs_time);
for (;;){
int res = sem_timedwait(handle, &tspec);
@@ -190,17 +221,16 @@ inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &
if(system_error_code() == ETIMEDOUT){
return false;
}
- throw interprocess_exception(system_error_code());
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
}
return false;
#else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
- boost::posix_time::ptime now;
- do{
- if(semaphore_try_wait(handle))
- return true;
- thread_yield();
- }while((now = microsec_clock::universal_time()) < abs_time);
- return false;
+
+ semaphore_wrapper_try_wrapper swtw(handle);
+ ipcdetail::lock_to_wait<semaphore_wrapper_try_wrapper> lw(swtw);
+ return ipcdetail::try_based_timed_lock(lw, abs_time);
+
#endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
}
diff --git a/boost/interprocess/sync/scoped_lock.hpp b/boost/interprocess/sync/scoped_lock.hpp
index 61fe93e5b3..c095530274 100644
--- a/boost/interprocess/sync/scoped_lock.hpp
+++ b/boost/interprocess/sync/scoped_lock.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -16,7 +16,7 @@
#ifndef BOOST_INTERPROCESS_SCOPED_LOCK_HPP
#define BOOST_INTERPROCESS_SCOPED_LOCK_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -27,7 +27,7 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
//!\file
@@ -50,12 +50,12 @@ namespace interprocess {
template <class Mutex>
class scoped_lock
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef scoped_lock<Mutex> this_type;
BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_lock)
typedef bool this_type::*unspecified_bool_type;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
typedef Mutex mutex_type;
@@ -157,7 +157,7 @@ class scoped_lock
//! a)if try_unlock_upgradable_and_lock() returns true then mutex() obtains
//! the value from upgr.release() and owns() is set to true.
//! b)if try_unlock_upgradable_and_lock() returns false then upgr is
- //! unaffected and this scoped_lock construction as the same effects as
+ //! unaffected and this scoped_lock construction as the same effects as
//! a default construction.
//! c)Else upgr.owns() is false. mutex() obtains the value from upgr.release()
//! and owns() is set to false
@@ -259,7 +259,7 @@ class scoped_lock
//! mutex after the assignment (and scop will not), but the mutex's lock
//! count will be decremented by one.
scoped_lock &operator=(BOOST_RV_REF(scoped_lock) scop)
- {
+ {
if(this->owns())
this->unlock();
m_locked = scop.owns();
@@ -357,11 +357,11 @@ class scoped_lock
std::swap(m_locked, other.m_locked);
}
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
mutex_type *mp_mutex;
bool m_locked;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
} // namespace interprocess
diff --git a/boost/interprocess/sync/sharable_lock.hpp b/boost/interprocess/sync/sharable_lock.hpp
index 9342e45a46..efbee6d10a 100644
--- a/boost/interprocess/sync/sharable_lock.hpp
+++ b/boost/interprocess/sync/sharable_lock.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -16,7 +16,7 @@
#ifndef BOOST_INTERPROCESS_SHARABLE_LOCK_HPP
#define BOOST_INTERPROCESS_SHARABLE_LOCK_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -27,7 +27,7 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
//!\file
@@ -51,13 +51,13 @@ class sharable_lock
{
public:
typedef SharableMutex mutex_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef sharable_lock<SharableMutex> this_type;
explicit sharable_lock(scoped_lock<mutex_type>&);
typedef bool this_type::*unspecified_bool_type;
BOOST_MOVABLE_BUT_NOT_COPYABLE(sharable_lock)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Effects: Default constructs a sharable_lock.
@@ -189,7 +189,7 @@ class sharable_lock
//! before the assignment. In this case, this will own the mutex after the assignment
//! (and upgr will not), but the mutex's lock count will be decremented by one.
sharable_lock &operator=(BOOST_RV_REF(sharable_lock<mutex_type>) upgr)
- {
+ {
if(this->owns())
this->unlock();
m_locked = upgr.owns();
@@ -203,7 +203,7 @@ class sharable_lock
//!Notes: The sharable_lock changes from a state of not owning the
//! mutex, to owning the mutex, blocking if necessary.
void lock()
- {
+ {
if(!mp_mutex || m_locked)
throw lock_exception();
mp_mutex->lock_sharable();
@@ -219,7 +219,7 @@ class sharable_lock
//! mutex_type does not support try_lock_sharable(), this function will
//! fail at compile time if instantiated, but otherwise have no effect.
bool try_lock()
- {
+ {
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->try_lock_sharable();
@@ -236,7 +236,7 @@ class sharable_lock
//! timed_lock_sharable(), this function will fail at compile time if
//! instantiated, but otherwise have no effect.
bool timed_lock(const boost::posix_time::ptime& abs_time)
- {
+ {
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->timed_lock_sharable(abs_time);
@@ -290,11 +290,11 @@ class sharable_lock
std::swap(m_locked, other.m_locked);
}
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
mutex_type *mp_mutex;
bool m_locked;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
} // namespace interprocess
diff --git a/boost/interprocess/sync/shm/named_condition.hpp b/boost/interprocess/sync/shm/named_condition.hpp
index 9d7cd77e11..e2ff280b7b 100644
--- a/boost/interprocess/sync/shm/named_condition.hpp
+++ b/boost/interprocess/sync/shm/named_condition.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP
#define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -29,8 +29,11 @@
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/permissions.hpp>
#if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
-#include <boost/interprocess/sync/interprocess_mutex.hpp>
-#include <boost/interprocess/sync/scoped_lock.hpp>
+ #include <boost/interprocess/sync/interprocess_mutex.hpp>
+ #include <boost/interprocess/sync/scoped_lock.hpp>
+ #include <boost/interprocess/sync/detail/condition_any_algorithm.hpp>
+#else
+ #include <boost/interprocess/sync/detail/locks.hpp>
#endif
@@ -41,21 +44,21 @@ namespace boost {
namespace interprocess {
namespace ipcdetail {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
class interprocess_tester;
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//! A global condition variable that can be created by name.
//! This condition variable is designed to work with named_mutex and
//! can't be placed in shared memory or memory mapped files.
class shm_named_condition
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
shm_named_condition();
shm_named_condition(const shm_named_condition &);
shm_named_condition &operator=(const shm_named_condition &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Creates a global condition with a name.
//!If the condition can't be created throws interprocess_exception
@@ -119,113 +122,44 @@ class shm_named_condition
//!Returns false on error. Never throws.
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
- struct condition_holder
+ #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
+ class internal_condition_members
{
- interprocess_condition cond_;
- //If named_mutex is implemented using semaphores
- //we need to store an additional mutex
- #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
- interprocess_mutex mutex_;
- #endif
- };
+ public:
+ typedef interprocess_mutex mutex_type;
+ typedef interprocess_condition condvar_type;
- interprocess_condition *condition() const
- { return &static_cast<condition_holder*>(m_shmem.get_user_address())->cond_; }
+ condvar_type& get_condvar() { return m_cond; }
+ mutex_type& get_mutex() { return m_mtx; }
- template <class Lock>
- class lock_inverter
- {
- Lock &l_;
- public:
- lock_inverter(Lock &l)
- : l_(l)
- {}
- void lock() { l_.unlock(); }
- void unlock() { l_.lock(); }
+ private:
+ mutex_type m_mtx;
+ condvar_type m_cond;
};
- //If named mutex uses POSIX semaphores, then the shm based condition variable
- //must use it's internal lock to wait, as sem_t does not store a pthread_mutex_t
- //instance needed by pthread_mutex_cond_t
- #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
- interprocess_mutex *mutex() const
- { return &static_cast<condition_holder*>(m_shmem.get_user_address())->mutex_; }
-
- template <class Lock>
- void do_wait(Lock& lock)
- {
- //shm_named_condition only works with named_mutex
- BOOST_STATIC_ASSERT((is_convertible<typename Lock::mutex_type&, named_mutex&>::value == true));
-
- //lock internal before unlocking external to avoid race with a notifier
- scoped_lock<interprocess_mutex> internal_lock(*this->mutex());
- lock_inverter<Lock> inverted_lock(lock);
- scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
-
- //unlock internal first to avoid deadlock with near simultaneous waits
- scoped_lock<interprocess_mutex> internal_unlock;
- internal_lock.swap(internal_unlock);
- this->condition()->wait(internal_unlock);
- }
-
- template <class Lock>
- bool do_timed_wait(Lock& lock, const boost::posix_time::ptime &abs_time)
- {
- //shm_named_condition only works with named_mutex
- BOOST_STATIC_ASSERT((is_convertible<typename Lock::mutex_type&, named_mutex&>::value == true));
- //lock internal before unlocking external to avoid race with a notifier
- scoped_lock<interprocess_mutex> internal_lock(*this->mutex(), abs_time);
- if(!internal_lock) return false;
- lock_inverter<Lock> inverted_lock(lock);
- scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
-
- //unlock internal first to avoid deadlock with near simultaneous waits
- scoped_lock<interprocess_mutex> internal_unlock;
- internal_lock.swap(internal_unlock);
- return this->condition()->timed_wait(internal_unlock, abs_time);
- }
- #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
- template<class Lock>
- class lock_wrapper
- {
- typedef void (lock_wrapper::*unspecified_bool_type)();
- public:
-
- typedef interprocess_mutex mutex_type;
-
- lock_wrapper(Lock &l)
- : l_(l)
- {}
-
- mutex_type* mutex() const
- { return l_.mutex()->mutex(); }
-
- void lock() { l_.lock(); }
-
- void unlock() { l_.unlock(); }
-
- operator unspecified_bool_type() const
- { return l_ ? &lock_wrapper::lock : 0; }
-
- private:
- Lock &l_;
- };
+ typedef ipcdetail::condition_any_wrapper<internal_condition_members> internal_condition;
+ #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
+ typedef interprocess_condition internal_condition;
#endif //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
+ internal_condition &internal_cond()
+ { return *static_cast<internal_condition*>(m_shmem.get_user_address()); }
+
friend class boost::interprocess::ipcdetail::interprocess_tester;
void dont_close_on_destruction();
- managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
+ open_create_impl_t m_shmem;
template <class T, class Arg> friend class boost::interprocess::ipcdetail::named_creation_functor;
- typedef boost::interprocess::ipcdetail::named_creation_functor<condition_holder> construct_func_t;
- /// @endcond
+ typedef boost::interprocess::ipcdetail::named_creation_functor<internal_condition> construct_func_t;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline shm_named_condition::~shm_named_condition()
{}
@@ -233,9 +167,8 @@ inline shm_named_condition::~shm_named_condition()
inline shm_named_condition::shm_named_condition(create_only_t, const char *name, const permissions &perm)
: m_shmem (create_only
,name
- ,sizeof(condition_holder) +
- managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ ,sizeof(internal_condition) +
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoCreate)
@@ -245,9 +178,8 @@ inline shm_named_condition::shm_named_condition(create_only_t, const char *name,
inline shm_named_condition::shm_named_condition(open_or_create_t, const char *name, const permissions &perm)
: m_shmem (open_or_create
,name
- ,sizeof(condition_holder) +
- managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ ,sizeof(internal_condition) +
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoOpenOrCreate)
@@ -265,113 +197,34 @@ inline shm_named_condition::shm_named_condition(open_only_t, const char *name)
inline void shm_named_condition::dont_close_on_destruction()
{ interprocess_tester::dont_close_on_destruction(m_shmem); }
-#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
-
inline void shm_named_condition::notify_one()
-{
- scoped_lock<interprocess_mutex> internal_lock(*this->mutex());
- this->condition()->notify_one();
-}
+{ this->internal_cond().notify_one(); }
inline void shm_named_condition::notify_all()
-{
- scoped_lock<interprocess_mutex> internal_lock(*this->mutex());
- this->condition()->notify_all();
-}
+{ this->internal_cond().notify_all(); }
template <typename L>
inline void shm_named_condition::wait(L& lock)
-{
- if (!lock)
- throw lock_exception();
- this->do_wait(lock);
-}
+{ this->internal_cond().wait(lock); }
template <typename L, typename Pr>
inline void shm_named_condition::wait(L& lock, Pr pred)
-{
- if (!lock)
- throw lock_exception();
- while (!pred())
- this->do_wait(lock);
-}
+{ this->internal_cond().wait(lock, pred); }
template <typename L>
inline bool shm_named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock);
- return true;
- }
- if (!lock)
- throw lock_exception();
- return this->do_timed_wait(lock, abs_time);
-}
+{ return this->internal_cond().timed_wait(lock, abs_time); }
template <typename L, typename Pr>
inline bool shm_named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock, pred);
- return true;
- }
- if (!lock)
- throw lock_exception();
-
- while (!pred()){
- if(!this->do_timed_wait(lock, abs_time)){
- return pred();
- }
- }
- return true;
-}
-
-#else
-
-inline void shm_named_condition::notify_one()
-{ this->condition()->notify_one(); }
-
-inline void shm_named_condition::notify_all()
-{ this->condition()->notify_all(); }
-
-template <typename L>
-inline void shm_named_condition::wait(L& lock)
-{
- lock_wrapper<L> newlock(lock);
- this->condition()->wait(newlock);
-}
-
-template <typename L, typename Pr>
-inline void shm_named_condition::wait(L& lock, Pr pred)
-{
- lock_wrapper<L> newlock(lock);
- this->condition()->wait(newlock, pred);
-}
-
-template <typename L>
-inline bool shm_named_condition::timed_wait
- (L& lock, const boost::posix_time::ptime &abs_time)
-{
- lock_wrapper<L> newlock(lock);
- return this->condition()->timed_wait(newlock, abs_time);
-}
-
-template <typename L, typename Pr>
-inline bool shm_named_condition::timed_wait
- (L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
-{
- lock_wrapper<L> newlock(lock);
- return this->condition()->timed_wait(newlock, abs_time, pred);
-}
-
-#endif
+{ return this->internal_cond().timed_wait(lock, abs_time, pred); }
inline bool shm_named_condition::remove(const char *name)
{ return shared_memory_object::remove(name); }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace ipcdetail
} //namespace interprocess
diff --git a/boost/interprocess/sync/shm/named_condition_any.hpp b/boost/interprocess/sync/shm/named_condition_any.hpp
new file mode 100644
index 0000000000..46bca92e45
--- /dev/null
+++ b/boost/interprocess/sync/shm/named_condition_any.hpp
@@ -0,0 +1,191 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP
+#define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/sync/interprocess_condition.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
+#include <boost/interprocess/sync/named_mutex.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/interprocess/sync/detail/condition_any_algorithm.hpp>
+
+//!\file
+//!Describes process-shared variables interprocess_condition class
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+class interprocess_tester;
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//! A global condition variable that can be created by name.
+//! This condition variable is designed to work with named_mutex and
+//! can't be placed in shared memory or memory mapped files.
+class shm_named_condition_any
+{
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ //Non-copyable
+ shm_named_condition_any();
+ shm_named_condition_any(const shm_named_condition_any &);
+ shm_named_condition_any &operator=(const shm_named_condition_any &);
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ public:
+ //!Creates a global condition with a name.
+ //!If the condition can't be created throws interprocess_exception
+ shm_named_condition_any(create_only_t create_only, const char *name, const permissions &perm = permissions())
+ : m_shmem (create_only
+ ,name
+ ,sizeof(internal_condition) +
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(DoCreate)
+ ,perm)
+ {}
+
+ //!Opens or creates a global condition with a name.
+ //!If the condition is created, this call is equivalent to
+ //!shm_named_condition_any(create_only_t, ... )
+ //!If the condition is already created, this call is equivalent
+ //!shm_named_condition_any(open_only_t, ... )
+ //!Does not throw
+ shm_named_condition_any(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions())
+ : m_shmem (open_or_create
+ ,name
+ ,sizeof(internal_condition) +
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(DoOpenOrCreate)
+ ,perm)
+ {}
+
+ //!Opens a global condition with a name if that condition is previously
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ shm_named_condition_any(open_only_t open_only, const char *name)
+ : m_shmem (open_only
+ ,name
+ ,read_write
+ ,0
+ ,construct_func_t(DoOpen))
+ {}
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~shm_named_condition_any()
+ {}
+
+ //!If there is a thread waiting on *this, change that
+ //!thread's state to ready. Otherwise there is no effect.*/
+ void notify_one()
+ { m_cond.notify_one(); }
+
+ //!Change the state of all threads waiting on *this to ready.
+ //!If there are no waiting threads, notify_all() has no effect.
+ void notify_all()
+ { m_cond.notify_all(); }
+
+ //!Releases the lock on the named_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), and then reacquires the lock.
+ template <typename L>
+ void wait(L& lock)
+ { m_cond.wait(lock); }
+
+ //!The same as:
+ //!while (!pred()) wait(lock)
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ { m_cond.wait(lock, pred); }
+
+ //!Releases the lock on the named_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
+ //!and then reacquires the lock.
+ //!Returns: false if time abs_time is reached, otherwise true.
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ { return m_cond.timed_wait(lock, abs_time); }
+
+ //!The same as: while (!pred()) {
+ //! if (!timed_wait(lock, abs_time)) return pred();
+ //! } return true;
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ { return m_cond.timed_wait(lock, abs_time, pred); }
+
+ //!Erases a named condition from the system.
+ //!Returns false on error. Never throws.
+ static bool remove(const char *name)
+ { return shared_memory_object::remove(name); }
+
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ private:
+
+ class internal_condition_members
+ {
+ public:
+ typedef interprocess_mutex mutex_type;
+ typedef interprocess_condition condvar_type;
+
+ condvar_type& get_condvar() { return m_cond; }
+ mutex_type& get_mutex() { return m_mtx; }
+
+ private:
+ mutex_type m_mtx;
+ condvar_type m_cond;
+ };
+
+ typedef ipcdetail::condition_any_wrapper<internal_condition_members> internal_condition;
+
+ internal_condition m_cond;
+
+ friend class boost::interprocess::ipcdetail::interprocess_tester;
+ void dont_close_on_destruction()
+ { interprocess_tester::dont_close_on_destruction(m_shmem); }
+
+ typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
+ open_create_impl_t m_shmem;
+
+ template <class T, class Arg> friend class boost::interprocess::ipcdetail::named_creation_functor;
+ typedef boost::interprocess::ipcdetail::named_creation_functor<internal_condition> construct_func_t;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+};
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP
diff --git a/boost/interprocess/sync/shm/named_creation_functor.hpp b/boost/interprocess/sync/shm/named_creation_functor.hpp
index 9d752c837a..234e072aac 100644
--- a/boost/interprocess/sync/shm/named_creation_functor.hpp
+++ b/boost/interprocess/sync/shm/named_creation_functor.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2007-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP
#define BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/mpl.hpp>
@@ -38,7 +42,7 @@ class named_creation_functor
{ new(address)T(m_arg); }
bool operator()(void *address, std::size_t, bool created) const
- {
+ {
switch(m_creation_type){
case DoOpen:
return true;
@@ -56,6 +60,10 @@ class named_creation_functor
break;
}
}
+
+ std::size_t get_min_size() const
+ { return sizeof(T); }
+
private:
create_enum_t m_creation_type;
Arg m_arg;
diff --git a/boost/interprocess/sync/shm/named_mutex.hpp b/boost/interprocess/sync/shm/named_mutex.hpp
index f32fa70044..fc66f3a704 100644
--- a/boost/interprocess/sync/shm/named_mutex.hpp
+++ b/boost/interprocess/sync/shm/named_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP
#define BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -42,14 +42,14 @@ class named_condition;
//!each process should have it's own named mutex.
class shm_named_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
shm_named_mutex();
shm_named_mutex(const shm_named_mutex &);
shm_named_mutex &operator=(const shm_named_mutex &);
friend class named_condition;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Creates a global interprocess_mutex with a name.
@@ -99,20 +99,21 @@ class shm_named_mutex
//!Returns false on error. Never throws.
static bool remove(const char *name);
- /// @cond
- interprocess_mutex *mutex() const
- { return static_cast<interprocess_mutex*>(m_shmem.get_user_address()); }
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ typedef interprocess_mutex internal_mutex_type;
+ interprocess_mutex &internal_mutex()
+ { return *static_cast<interprocess_mutex*>(m_shmem.get_user_address()); }
private:
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction();
-
- ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
+ open_create_impl_t m_shmem;
typedef ipcdetail::named_creation_functor<interprocess_mutex> construct_func_t;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void shm_named_mutex::dont_close_on_destruction()
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); }
@@ -124,8 +125,7 @@ inline shm_named_mutex::shm_named_mutex(create_only_t, const char *name, const p
: m_shmem (create_only
,name
,sizeof(interprocess_mutex) +
- ipcdetail::managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoCreate)
@@ -136,8 +136,7 @@ inline shm_named_mutex::shm_named_mutex(open_or_create_t, const char *name, cons
: m_shmem (open_or_create
,name
,sizeof(interprocess_mutex) +
- ipcdetail::managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoOpenOrCreate)
@@ -153,27 +152,21 @@ inline shm_named_mutex::shm_named_mutex(open_only_t, const char *name)
{}
inline void shm_named_mutex::lock()
-{ this->mutex()->lock(); }
+{ this->internal_mutex().lock(); }
inline void shm_named_mutex::unlock()
-{ this->mutex()->unlock(); }
+{ this->internal_mutex().unlock(); }
inline bool shm_named_mutex::try_lock()
-{ return this->mutex()->try_lock(); }
+{ return this->internal_mutex().try_lock(); }
inline bool shm_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
- return this->mutex()->timed_lock(abs_time);
-}
+{ return this->internal_mutex().timed_lock(abs_time); }
inline bool shm_named_mutex::remove(const char *name)
{ return shared_memory_object::remove(name); }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace ipcdetail {
} //namespace interprocess {
diff --git a/boost/interprocess/sync/shm/named_recursive_mutex.hpp b/boost/interprocess/sync/shm/named_recursive_mutex.hpp
index 7235571254..988ef66315 100644
--- a/boost/interprocess/sync/shm/named_recursive_mutex.hpp
+++ b/boost/interprocess/sync/shm/named_recursive_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP
#define BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -33,18 +33,18 @@ namespace boost {
namespace interprocess {
namespace ipcdetail {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
class interprocess_tester;
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
class shm_named_recursive_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
shm_named_recursive_mutex();
shm_named_recursive_mutex(const shm_named_recursive_mutex &);
shm_named_recursive_mutex &operator=(const shm_named_recursive_mutex &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Creates a global recursive_mutex with a name.
@@ -94,17 +94,17 @@ class shm_named_recursive_mutex
//!from the system
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class interprocess_tester;
void dont_close_on_destruction();
interprocess_recursive_mutex *mutex() const
{ return static_cast<interprocess_recursive_mutex*>(m_shmem.get_user_address()); }
-
- managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
+ open_create_impl_t m_shmem;
typedef named_creation_functor<interprocess_recursive_mutex> construct_func_t;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
inline shm_named_recursive_mutex::~shm_named_recursive_mutex()
@@ -117,8 +117,7 @@ inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const
: m_shmem (create_only
,name
,sizeof(interprocess_recursive_mutex) +
- managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoCreate)
@@ -129,8 +128,7 @@ inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, co
: m_shmem (open_or_create
,name
,sizeof(interprocess_recursive_mutex) +
- managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoOpenOrCreate)
@@ -155,13 +153,7 @@ inline bool shm_named_recursive_mutex::try_lock()
{ return this->mutex()->try_lock(); }
inline bool shm_named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
- return this->mutex()->timed_lock(abs_time);
-}
+{ return this->mutex()->timed_lock(abs_time); }
inline bool shm_named_recursive_mutex::remove(const char *name)
{ return shared_memory_object::remove(name); }
diff --git a/boost/interprocess/sync/shm/named_semaphore.hpp b/boost/interprocess/sync/shm/named_semaphore.hpp
index c6d3830db5..d952d12e14 100644
--- a/boost/interprocess/sync/shm/named_semaphore.hpp
+++ b/boost/interprocess/sync/shm/named_semaphore.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP
#define BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -33,13 +33,13 @@ namespace ipcdetail {
class shm_named_semaphore
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
shm_named_semaphore();
shm_named_semaphore(const shm_named_semaphore &);
shm_named_semaphore &operator=(const shm_named_semaphore &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
shm_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions());
@@ -57,7 +57,7 @@ class shm_named_semaphore
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class interprocess_tester;
void dont_close_on_destruction();
@@ -65,9 +65,10 @@ class shm_named_semaphore
interprocess_semaphore *semaphore() const
{ return static_cast<interprocess_semaphore*>(m_shmem.get_user_address()); }
- managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
+ open_create_impl_t m_shmem;
typedef named_creation_functor<interprocess_semaphore, int> construct_func_t;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
inline shm_named_semaphore::~shm_named_semaphore()
@@ -81,8 +82,7 @@ inline shm_named_semaphore::shm_named_semaphore
: m_shmem (create_only
,name
,sizeof(interprocess_semaphore) +
- managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoCreate, initialCount)
@@ -94,8 +94,7 @@ inline shm_named_semaphore::shm_named_semaphore
: m_shmem (open_or_create
,name
,sizeof(interprocess_semaphore) +
- managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoOpenOrCreate, initialCount)
@@ -121,13 +120,7 @@ inline bool shm_named_semaphore::try_wait()
{ return semaphore()->try_wait(); }
inline bool shm_named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait();
- return true;
- }
- return semaphore()->timed_wait(abs_time);
-}
+{ return semaphore()->timed_wait(abs_time); }
inline bool shm_named_semaphore::remove(const char *name)
{ return shared_memory_object::remove(name); }
diff --git a/boost/interprocess/sync/shm/named_upgradable_mutex.hpp b/boost/interprocess/sync/shm/named_upgradable_mutex.hpp
index 0975a6ed2b..4c397927fb 100644
--- a/boost/interprocess/sync/shm/named_upgradable_mutex.hpp
+++ b/boost/interprocess/sync/shm/named_upgradable_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP
#define BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -32,9 +32,9 @@
namespace boost {
namespace interprocess {
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail{ class interprocess_tester; }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
class named_condition;
@@ -43,13 +43,13 @@ class named_condition;
//!each process should have it's own named upgradable mutex.
class named_upgradable_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
named_upgradable_mutex();
named_upgradable_mutex(const named_upgradable_mutex &);
named_upgradable_mutex &operator=(const named_upgradable_mutex &);
friend class named_condition;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Creates a global upgradable mutex with a name.
@@ -221,7 +221,7 @@ class named_upgradable_mutex
//!Returns false on error. Never throws.
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction();
@@ -229,12 +229,13 @@ class named_upgradable_mutex
interprocess_upgradable_mutex *mutex() const
{ return static_cast<interprocess_upgradable_mutex*>(m_shmem.get_user_address()); }
- ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
+ open_create_impl_t m_shmem;
typedef ipcdetail::named_creation_functor<interprocess_upgradable_mutex> construct_func_t;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_upgradable_mutex::~named_upgradable_mutex()
{}
@@ -244,8 +245,7 @@ inline named_upgradable_mutex::named_upgradable_mutex
: m_shmem (create_only
,name
,sizeof(interprocess_upgradable_mutex) +
- ipcdetail::managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoCreate)
@@ -257,8 +257,7 @@ inline named_upgradable_mutex::named_upgradable_mutex
: m_shmem (open_or_create
,name
,sizeof(interprocess_upgradable_mutex) +
- ipcdetail::managed_open_or_create_impl<shared_memory_object>::
- ManagedOpenOrCreateUserOffset
+ open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoOpenOrCreate)
@@ -288,13 +287,7 @@ inline bool named_upgradable_mutex::try_lock()
inline bool named_upgradable_mutex::timed_lock
(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
- return this->mutex()->timed_lock(abs_time);
-}
+{ return this->mutex()->timed_lock(abs_time); }
inline void named_upgradable_mutex::lock_upgradable()
{ this->mutex()->lock_upgradable(); }
@@ -307,13 +300,7 @@ inline bool named_upgradable_mutex::try_lock_upgradable()
inline bool named_upgradable_mutex::timed_lock_upgradable
(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock_upgradable();
- return true;
- }
- return this->mutex()->timed_lock_upgradable(abs_time);
-}
+{ return this->mutex()->timed_lock_upgradable(abs_time); }
inline void named_upgradable_mutex::lock_sharable()
{ this->mutex()->lock_sharable(); }
@@ -326,13 +313,7 @@ inline bool named_upgradable_mutex::try_lock_sharable()
inline bool named_upgradable_mutex::timed_lock_sharable
(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock_sharable();
- return true;
- }
- return this->mutex()->timed_lock_sharable(abs_time);
-}
+{ return this->mutex()->timed_lock_sharable(abs_time); }
inline void named_upgradable_mutex::unlock_and_lock_upgradable()
{ this->mutex()->unlock_and_lock_upgradable(); }
@@ -362,7 +343,7 @@ inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
inline bool named_upgradable_mutex::remove(const char *name)
{ return shared_memory_object::remove(name); }
-/// @endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/sync/spin/condition.hpp b/boost/interprocess/sync/spin/condition.hpp
index 55dd79b406..e587c32c9b 100644
--- a/boost/interprocess/sync/spin/condition.hpp
+++ b/boost/interprocess/sync/spin/condition.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP
#define BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/spin/mutex.hpp>
@@ -19,7 +23,8 @@
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
-#include <boost/move/move.hpp>
+#include <boost/interprocess/sync/spin/wait.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/cstdint.hpp>
namespace boost {
@@ -40,24 +45,26 @@ class spin_condition
template <typename L>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
{
+ if (!lock)
+ throw lock_exception();
+ //Handle infinity absolute time here to avoid complications in do_timed_wait
if(abs_time == boost::posix_time::pos_infin){
this->wait(lock);
return true;
}
- if (!lock)
- throw lock_exception();
return this->do_timed_wait(abs_time, *lock.mutex());
}
template <typename L, typename Pr>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
{
+ if (!lock)
+ throw lock_exception();
+ //Handle infinity absolute time here to avoid complications in do_timed_wait
if(abs_time == boost::posix_time::pos_infin){
this->wait(lock, pred);
return true;
}
- if (!lock)
- throw lock_exception();
while (!pred()){
if (!this->do_timed_wait(abs_time, *lock.mutex()))
return pred();
@@ -110,8 +117,10 @@ inline spin_condition::spin_condition()
}
inline spin_condition::~spin_condition()
-{
- //Trivial destructor
+{
+ //Notify all waiting threads
+ //to allow POSIX semantics on condition destruction
+ this->notify_all();
}
inline void spin_condition::notify_one()
@@ -140,15 +149,10 @@ inline void spin_condition::notify(boost::uint32_t command)
}
//Notify that all threads should execute wait logic
+ spin_wait swait;
while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), command, SLEEP)){
- thread_yield();
+ swait.yield();
}
-/*
- //Wait until the threads are woken
- while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), 0)){
- thread_yield();
- }
-*/
//The enter mutex will rest locked until the last waiting thread unlocks it
}
@@ -171,7 +175,7 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled,
InterprocessMutex &mut)
{
boost::posix_time::ptime now = microsec_clock::universal_time();
-
+
if(tout_enabled){
if(now >= abs_time) return false;
}
@@ -205,14 +209,15 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled,
//By default, we suppose that no timeout has happened
bool timed_out = false, unlock_enter_mut= false;
-
+
//Loop until a notification indicates that the thread should
//exit or timeout occurs
while(1){
//The thread sleeps/spins until a spin_condition commands a notification
//Notification occurred, we will lock the checking mutex so that
+ spin_wait swait;
while(atomic_read32(&m_command) == SLEEP){
- thread_yield();
+ swait.yield();
//Check for timeout
if(tout_enabled){
@@ -253,7 +258,7 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled,
continue;
}
else if(result == NOTIFY_ONE){
- //If it was a NOTIFY_ONE command, only this thread should
+ //If it was a NOTIFY_ONE command, only this thread should
//exit. This thread has atomically marked command as sleep before
//so no other thread will exit.
//Decrement wait count.
diff --git a/boost/interprocess/sync/spin/interprocess_barrier.hpp b/boost/interprocess/sync/spin/interprocess_barrier.hpp
index f8ee09948d..5f88dd4faa 100644
--- a/boost/interprocess/sync/spin/interprocess_barrier.hpp
+++ b/boost/interprocess/sync/spin/interprocess_barrier.hpp
@@ -12,6 +12,10 @@
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
namespace boost {
namespace interprocess {
diff --git a/boost/interprocess/sync/spin/mutex.hpp b/boost/interprocess/sync/spin/mutex.hpp
index 926f7237c0..154dc6d916 100644
--- a/boost/interprocess/sync/spin/mutex.hpp
+++ b/boost/interprocess/sync/spin/mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP
#define BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -22,6 +22,7 @@
#include <boost/interprocess/detail/atomic.hpp>
#include <boost/cstdint.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/sync/detail/common_algorithms.hpp>
namespace boost {
namespace interprocess {
@@ -59,48 +60,16 @@ inline spin_mutex::~spin_mutex()
}
inline void spin_mutex::lock(void)
-{
- do{
- boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
-
- if (m_s == 1 && prev_s == 0){
- break;
- }
- // relinquish current timeslice
- ipcdetail::thread_yield();
- }while (true);
-}
+{ return ipcdetail::try_based_lock(*this); }
inline bool spin_mutex::try_lock(void)
{
- boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
+ boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
return m_s == 1 && prev_s == 0;
}
inline bool spin_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
-{
- 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();
-
- do{
- if(this->try_lock()){
- break;
- }
- now = microsec_clock::universal_time();
-
- if(now >= abs_time){
- return false;
- }
- // relinquish current time slice
- ipcdetail::thread_yield();
- }while (true);
-
- return true;
-}
+{ return ipcdetail::try_based_timed_lock(*this, abs_time); }
inline void spin_mutex::unlock(void)
{ ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 0, 1); }
diff --git a/boost/interprocess/sync/spin/recursive_mutex.hpp b/boost/interprocess/sync/spin/recursive_mutex.hpp
index a763f9c72d..ce6b0d18ac 100644
--- a/boost/interprocess/sync/spin/recursive_mutex.hpp
+++ b/boost/interprocess/sync/spin/recursive_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -27,7 +27,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP
#define BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -118,10 +118,6 @@ inline bool spin_recursive_mutex::try_lock()
inline bool spin_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
handle_t old_id;
ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
@@ -133,6 +129,7 @@ inline bool spin_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs
++m_nLockCount;
return true;
}
+ //m_mutex supports abs_time so no need to check it
if(m_mutex.timed_lock(abs_time)){
ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
m_nLockCount = 1;
diff --git a/boost/interprocess/sync/spin/semaphore.hpp b/boost/interprocess/sync/spin/semaphore.hpp
index 1b8cac35aa..94922afe43 100644
--- a/boost/interprocess/sync/spin/semaphore.hpp
+++ b/boost/interprocess/sync/spin/semaphore.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP
#define BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -20,6 +20,8 @@
#include <boost/interprocess/detail/atomic.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/detail/common_algorithms.hpp>
+#include <boost/interprocess/sync/detail/locks.hpp>
#include <boost/cstdint.hpp>
namespace boost {
@@ -59,11 +61,8 @@ inline void spin_semaphore::post()
inline void spin_semaphore::wait()
{
- while(!ipcdetail::atomic_add_unless32(&m_count, boost::uint32_t(-1), boost::uint32_t(0))){
- while(ipcdetail::atomic_read32(&m_count) == 0){
- ipcdetail::thread_yield();
- }
- }
+ ipcdetail::lock_to_wait<spin_semaphore> lw(*this);
+ return ipcdetail::try_based_lock(lw);
}
inline bool spin_semaphore::try_wait()
@@ -73,29 +72,10 @@ inline bool spin_semaphore::try_wait()
inline bool spin_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait();
- return true;
- }
- //Obtain current count and target time
- boost::posix_time::ptime now(microsec_clock::universal_time());
-
- do{
- if(this->try_wait()){
- break;
- }
- now = microsec_clock::universal_time();
-
- if(now >= abs_time){
- return this->try_wait();
- }
- // relinquish current time slice
- ipcdetail::thread_yield();
- }while (true);
- return true;
+ ipcdetail::lock_to_wait<spin_semaphore> lw(*this);
+ return ipcdetail::try_based_timed_lock(lw, abs_time);
}
-
//inline int spin_semaphore::get_count() const
//{
//return (int)ipcdetail::atomic_read32(&m_count);
diff --git a/boost/interprocess/sync/spin/wait.hpp b/boost/interprocess/sync/spin/wait.hpp
new file mode 100644
index 0000000000..220699bae1
--- /dev/null
+++ b/boost/interprocess/sync/spin/wait.hpp
@@ -0,0 +1,181 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Peter Dimov 2008.
+// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//Parts of this file come from boost/smart_ptr/detail/yield_k.hpp
+//Many thanks to Peter Dimov.
+
+#ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
+#define BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+
+//#define BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
+#ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
+#include <iostream>
+#endif
+
+// BOOST_INTERPROCESS_SMT_PAUSE
+
+#if defined(_MSC_VER) && ( defined(_M_IX86) || defined(_M_X64) )
+
+extern "C" void _mm_pause();
+#pragma intrinsic( _mm_pause )
+
+#define BOOST_INTERPROCESS_SMT_PAUSE _mm_pause();
+
+#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) && !defined(_CRAYC)
+
+#define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
+
+#endif
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail {
+
+template<int Dummy = 0>
+class num_core_holder
+{
+ public:
+ static unsigned int get()
+ {
+ if(!num_cores){
+ return ipcdetail::get_num_cores();
+ }
+ else{
+ return num_cores;
+ }
+ }
+
+ private:
+ static unsigned int num_cores;
+};
+
+template<int Dummy>
+unsigned int num_core_holder<Dummy>::num_cores = ipcdetail::get_num_cores();
+
+} //namespace ipcdetail {
+
+class spin_wait
+{
+ public:
+
+ static const unsigned int nop_pause_limit = 32u;
+ spin_wait()
+ : m_count_start(), m_ul_yield_only_counts(), m_k()
+ {}
+
+ #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
+ ~spin_wait()
+ {
+ if(m_k){
+ std::cout << "final m_k: " << m_k
+ << " system tick(us): " << ipcdetail::get_system_tick_us() << std::endl;
+ }
+ }
+ #endif
+
+ unsigned int count() const
+ { return m_k; }
+
+ void yield()
+ {
+ //Lazy initialization of limits
+ if( !m_k){
+ this->init_limits();
+ }
+ //Nop tries
+ if( m_k < (nop_pause_limit >> 2) ){
+
+ }
+ //Pause tries if the processor supports it
+ #if defined(BOOST_INTERPROCESS_SMT_PAUSE)
+ else if( m_k < nop_pause_limit ){
+ BOOST_INTERPROCESS_SMT_PAUSE
+ }
+ #endif
+ //Yield/Sleep strategy
+ else{
+ //Lazy initialization of tick information
+ if(m_k == nop_pause_limit){
+ this->init_tick_info();
+ }
+ else if( this->yield_or_sleep() ){
+ ipcdetail::thread_yield();
+ }
+ else{
+ ipcdetail::thread_sleep_tick();
+ }
+ }
+ ++m_k;
+ }
+
+ void reset()
+ {
+ m_k = 0u;
+ }
+
+ private:
+
+ void init_limits()
+ {
+ unsigned int num_cores = ipcdetail::num_core_holder<0>::get();
+ m_k = num_cores > 1u ? 0u : nop_pause_limit;
+ }
+
+ void init_tick_info()
+ {
+ m_ul_yield_only_counts = ipcdetail::get_system_tick_in_highres_counts();
+ m_count_start = ipcdetail::get_current_system_highres_count();
+ }
+
+ //Returns true if yield must be called, false is sleep must be called
+ bool yield_or_sleep()
+ {
+ if(!m_ul_yield_only_counts){ //If yield-only limit was reached then yield one in every two tries
+ return (m_k & 1u) != 0;
+ }
+ else{ //Try to see if we've reched yield-only time limit
+ const ipcdetail::OS_highres_count_t now = ipcdetail::get_current_system_highres_count();
+ const ipcdetail::OS_highres_count_t elapsed = ipcdetail::system_highres_count_subtract(now, m_count_start);
+ if(!ipcdetail::system_highres_count_less_ul(elapsed, m_ul_yield_only_counts)){
+ #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
+ std::cout << "elapsed!\n"
+ << " m_ul_yield_only_counts: " << m_ul_yield_only_counts
+ << " system tick(us): " << ipcdetail::get_system_tick_us() << '\n'
+ << " m_k: " << m_k << " elapsed counts: ";
+ ipcdetail::ostream_highres_count(std::cout, elapsed) << std::endl;
+ #endif
+ //Yield-only time reached, now it's time to sleep
+ m_ul_yield_only_counts = 0ul;
+ return false;
+ }
+ }
+ return true; //Otherwise yield
+ }
+
+ ipcdetail::OS_highres_count_t m_count_start;
+ unsigned long m_ul_yield_only_counts;
+ unsigned int m_k;
+};
+
+} // namespace interprocess
+} // namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
diff --git a/boost/interprocess/sync/upgradable_lock.hpp b/boost/interprocess/sync/upgradable_lock.hpp
index fb86374ca1..646019b433 100644
--- a/boost/interprocess/sync/upgradable_lock.hpp
+++ b/boost/interprocess/sync/upgradable_lock.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -16,7 +16,7 @@
#ifndef BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP
#define BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -28,7 +28,7 @@
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/exceptions.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
//!\file
@@ -52,13 +52,13 @@ class upgradable_lock
{
public:
typedef UpgradableMutex mutex_type;
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef upgradable_lock<UpgradableMutex> this_type;
explicit upgradable_lock(scoped_lock<mutex_type>&);
typedef bool this_type::*unspecified_bool_type;
BOOST_MOVABLE_BUT_NOT_COPYABLE(upgradable_lock)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Effects: Default constructs a upgradable_lock.
@@ -207,7 +207,7 @@ class upgradable_lock
//!Notes: The sharable_lock changes from a state of not owning the mutex,
//! to owning the mutex, blocking if necessary.
void lock()
- {
+ {
if(!mp_mutex || m_locked)
throw lock_exception();
mp_mutex->lock_upgradable();
@@ -223,7 +223,7 @@ class upgradable_lock
//! mutex_type does not support try_lock_upgradable(), this function will
//! fail at compile time if instantiated, but otherwise have no effect.
bool try_lock()
- {
+ {
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->try_lock_upgradable();
@@ -240,7 +240,7 @@ class upgradable_lock
//! timed_lock_upgradable(abs_time), this function will fail at compile
//! time if instantiated, but otherwise have no effect.
bool timed_lock(const boost::posix_time::ptime& abs_time)
- {
+ {
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->timed_lock_upgradable(abs_time);
@@ -294,11 +294,11 @@ class upgradable_lock
std::swap(m_locked, other.m_locked);
}
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
mutex_type *mp_mutex;
bool m_locked;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
} // namespace interprocess
diff --git a/boost/interprocess/sync/windows/condition.hpp b/boost/interprocess/sync/windows/condition.hpp
index 9695c21044..d5b77c7efe 100644
--- a/boost/interprocess/sync/windows/condition.hpp
+++ b/boost/interprocess/sync/windows/condition.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP
#define BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
@@ -33,63 +37,38 @@ class windows_condition
windows_condition &operator=(const windows_condition &);
public:
- windows_condition();
- ~windows_condition();
+ windows_condition()
+ : m_condition_data()
+ {}
+
+ ~windows_condition()
+ {
+ //Notify all waiting threads
+ //to allow POSIX semantics on condition destruction
+ this->notify_all();
+ }
+
+ void notify_one()
+ { m_condition_data.notify_one(); }
- void notify_one();
- void notify_all();
+ void notify_all()
+ { m_condition_data.notify_all(); }
template <typename L>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
- {
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock);
- return true;
- }
- if (!lock)
- throw lock_exception();
- return this->do_timed_wait(abs_time, *lock.mutex());
- }
+ { return m_condition_data.timed_wait(lock, abs_time); }
template <typename L, typename Pr>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
- {
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock, pred);
- return true;
- }
- if (!lock)
- throw lock_exception();
- while (!pred()){
- if (!this->do_timed_wait(abs_time, *lock.mutex()))
- return pred();
- }
- return true;
- }
+ { return m_condition_data.timed_wait(lock, abs_time, pred); }
template <typename L>
void wait(L& lock)
- {
- if (!lock)
- throw lock_exception();
- do_wait(*lock.mutex());
- }
+ { m_condition_data.wait(lock); }
template <typename L, typename Pr>
void wait(L& lock, Pr pred)
- {
- if (!lock)
- throw lock_exception();
-
- while (!pred())
- do_wait(*lock.mutex());
- }
-
- template<class InterprocessMutex>
- void do_wait(InterprocessMutex &mut);
-
- template<class InterprocessMutex>
- bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
+ { m_condition_data.wait(lock, pred); }
private:
@@ -132,33 +111,11 @@ class windows_condition
windows_semaphore m_sem_block_queue;
windows_semaphore m_sem_block_lock;
windows_mutex m_mtx_unblock_lock;
- } m_condition_data;
+ };
- typedef condition_algorithm_8a<condition_data> algorithm_type;
+ ipcdetail::condition_8a_wrapper<condition_data> m_condition_data;
};
-inline windows_condition::windows_condition()
- : m_condition_data()
-{}
-
-inline windows_condition::~windows_condition()
-{}
-
-inline void windows_condition::notify_one()
-{ algorithm_type::signal(m_condition_data, false); }
-
-inline void windows_condition::notify_all()
-{ algorithm_type::signal(m_condition_data, true); }
-
-template<class InterprocessMutex>
-inline void windows_condition::do_wait(InterprocessMutex &mut)
-{ algorithm_type::wait(m_condition_data, false, boost::posix_time::ptime(), mut); }
-
-template<class InterprocessMutex>
-inline bool windows_condition::do_timed_wait
- (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut)
-{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); }
-
} //namespace ipcdetail
} //namespace interprocess
} //namespace boost
diff --git a/boost/interprocess/sync/windows/mutex.hpp b/boost/interprocess/sync/windows/mutex.hpp
index 477acd396a..0b1958cfb7 100644
--- a/boost/interprocess/sync/windows/mutex.hpp
+++ b/boost/interprocess/sync/windows/mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
#define BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -57,8 +57,8 @@ inline windows_mutex::windows_mutex()
bool open_or_created;
(void)handles.obtain_mutex(this->id_, &open_or_created);
//The mutex must be created, never opened
- assert(open_or_created);
- assert(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
+ BOOST_ASSERT(open_or_created);
+ BOOST_ASSERT(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
(void)open_or_created;
}
diff --git a/boost/interprocess/sync/windows/named_condition.hpp b/boost/interprocess/sync/windows/named_condition.hpp
index 403e826178..ba220fdc5b 100644
--- a/boost/interprocess/sync/windows/named_condition.hpp
+++ b/boost/interprocess/sync/windows/named_condition.hpp
@@ -11,319 +11,19 @@
#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP
#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <boost/interprocess/creation_tags.hpp>
-#include <boost/interprocess/permissions.hpp>
-#include <boost/interprocess/detail/interprocess_tester.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
-#include <boost/interprocess/sync/windows/named_sync.hpp>
-#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
-#include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp>
+#include <boost/interprocess/sync/windows/named_condition_any.hpp>
namespace boost {
namespace interprocess {
namespace ipcdetail {
-class windows_named_condition
-{
- /// @cond
-
- //Non-copyable
- windows_named_condition();
- windows_named_condition(const windows_named_condition &);
- windows_named_condition &operator=(const windows_named_condition &);
- /// @endcond
-
- public:
- windows_named_condition(create_only_t, const char *name, const permissions &perm = permissions());
-
- windows_named_condition(open_or_create_t, const char *name, const permissions &perm = permissions());
-
- windows_named_condition(open_only_t, const char *name);
-
- ~windows_named_condition();
-
- //!If there is a thread waiting on *this, change that
- //!thread's state to ready. Otherwise there is no effect.*/
- void notify_one();
-
- //!Change the state of all threads waiting on *this to ready.
- //!If there are no waiting threads, notify_all() has no effect.
- void notify_all();
-
- //!Releases the lock on the named_mutex object associated with lock, blocks
- //!the current thread of execution until readied by a call to
- //!this->notify_one() or this->notify_all(), and then reacquires the lock.
- template <typename L>
- void wait(L& lock);
-
- //!The same as:
- //!while (!pred()) wait(lock)
- template <typename L, typename Pr>
- void wait(L& lock, Pr pred);
-
- //!Releases the lock on the named_mutex object associated with lock, blocks
- //!the current thread of execution until readied by a call to
- //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
- //!and then reacquires the lock.
- //!Returns: false if time abs_time is reached, otherwise true.
- template <typename L>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time);
-
- //!The same as: while (!pred()) {
- //! if (!timed_wait(lock, abs_time)) return pred();
- //! } return true;
- template <typename L, typename Pr>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred);
-
- static bool remove(const char *name);
-
- /// @cond
- private:
- friend class interprocess_tester;
- void dont_close_on_destruction();
-
- template <class InterprocessMutex>
- void do_wait(InterprocessMutex& lock);
-
- template <class InterprocessMutex>
- bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex& lock);
-
- struct condition_data
- {
- typedef boost::int32_t integer_type;
- typedef winapi_semaphore_wrapper semaphore_type;
- typedef winapi_mutex_wrapper mutex_type;
-
- integer_type &get_nwaiters_blocked()
- { return m_nwaiters_blocked; }
-
- integer_type &get_nwaiters_gone()
- { return m_nwaiters_gone; }
-
- integer_type &get_nwaiters_to_unblock()
- { return m_nwaiters_to_unblock; }
-
- semaphore_type &get_sem_block_queue()
- { return m_sem_block_queue; }
-
- semaphore_type &get_sem_block_lock()
- { return m_sem_block_lock; }
-
- mutex_type &get_mtx_unblock_lock()
- { return m_mtx_unblock_lock; }
-
- integer_type m_nwaiters_blocked;
- integer_type m_nwaiters_gone;
- integer_type m_nwaiters_to_unblock;
- winapi_semaphore_wrapper m_sem_block_queue;
- winapi_semaphore_wrapper m_sem_block_lock;
- winapi_mutex_wrapper m_mtx_unblock_lock;
- } m_condition_data;
-
- typedef condition_algorithm_8a<condition_data> algorithm_type;
-
- class named_cond_callbacks : public windows_named_sync_interface
- {
- typedef __int64 sem_count_t;
- mutable sem_count_t sem_counts [2];
-
- public:
- named_cond_callbacks(condition_data &cond_data)
- : m_condition_data(cond_data)
- {}
-
- virtual std::size_t get_data_size() const
- { return sizeof(sem_counts); }
-
- virtual const void *buffer_with_final_data_to_file()
- {
- sem_counts[0] = m_condition_data.m_sem_block_queue.value();
- sem_counts[1] = m_condition_data.m_sem_block_lock.value();
- return &sem_counts;
- }
-
- virtual const void *buffer_with_init_data_to_file()
- {
- sem_counts[0] = 0;
- sem_counts[1] = 1;
- return &sem_counts;
- }
-
- virtual void *buffer_to_store_init_data_from_file()
- { return &sem_counts; }
-
- virtual bool open(create_enum_t, const char *id_name)
- {
- m_condition_data.m_nwaiters_blocked = 0;
- m_condition_data.m_nwaiters_gone = 0;
- m_condition_data.m_nwaiters_to_unblock = 0;
-
- //Now open semaphores and mutex.
- //Use local variables + swap to guarantee consistent
- //initialization and cleanup in case any opening fails
- permissions perm;
- perm.set_unrestricted();
- std::string aux_str = "Global\\bipc.cond.";
- aux_str += id_name;
- std::size_t pos = aux_str.size();
-
- //sem_block_queue
- aux_str += "_bq";
- winapi_semaphore_wrapper sem_block_queue;
- bool created;
- if(!sem_block_queue.open_or_create
- (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created))
- return false;
- aux_str.erase(pos);
-
- //sem_block_lock
- aux_str += "_bl";
- winapi_semaphore_wrapper sem_block_lock;
- if(!sem_block_lock.open_or_create
- (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created))
- return false;
- aux_str.erase(pos);
-
- //mtx_unblock_lock
- aux_str += "_ul";
- winapi_mutex_wrapper mtx_unblock_lock;
- if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm))
- return false;
-
- //All ok, commit data
- m_condition_data.m_sem_block_queue.swap(sem_block_queue);
- m_condition_data.m_sem_block_lock.swap(sem_block_lock);
- m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock);
- return true;
- }
-
- virtual void close()
- {
- m_condition_data.m_sem_block_queue.close();
- m_condition_data.m_sem_block_lock.close();
- m_condition_data.m_mtx_unblock_lock.close();
- m_condition_data.m_nwaiters_blocked = 0;
- m_condition_data.m_nwaiters_gone = 0;
- m_condition_data.m_nwaiters_to_unblock = 0;
- }
-
- virtual ~named_cond_callbacks()
- {}
-
- private:
- condition_data &m_condition_data;
- };
-
- windows_named_sync m_named_sync;
- /// @endcond
-};
-
-inline windows_named_condition::~windows_named_condition()
-{
- named_cond_callbacks callbacks(m_condition_data);
- m_named_sync.close(callbacks);
-}
-
-inline void windows_named_condition::dont_close_on_destruction()
-{}
-
-inline windows_named_condition::windows_named_condition
- (create_only_t, const char *name, const permissions &perm)
- : m_condition_data()
-{
- named_cond_callbacks callbacks(m_condition_data);
- m_named_sync.open_or_create(DoCreate, name, perm, callbacks);
-}
-
-inline windows_named_condition::windows_named_condition
- (open_or_create_t, const char *name, const permissions &perm)
- : m_condition_data()
-{
- named_cond_callbacks callbacks(m_condition_data);
- m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks);
-}
-
-inline windows_named_condition::windows_named_condition(open_only_t, const char *name)
- : m_condition_data()
-{
- named_cond_callbacks callbacks(m_condition_data);
- m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks);
-}
-
-inline void windows_named_condition::notify_one()
-{ algorithm_type::signal(m_condition_data, false); }
-
-inline void windows_named_condition::notify_all()
-{ algorithm_type::signal(m_condition_data, true); }
-
-template<class InterprocessMutex>
-inline void windows_named_condition::do_wait(InterprocessMutex &mut)
-{ algorithm_type::wait(m_condition_data, false, boost::posix_time::ptime(), mut); }
-
-template<class InterprocessMutex>
-inline bool windows_named_condition::do_timed_wait
- (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut)
-{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); }
-
-template <typename L>
-inline void windows_named_condition::wait(L& lock)
-{
- if (!lock)
- throw lock_exception();
- this->do_wait(*lock.mutex());
-}
-
-template <typename L, typename Pr>
-inline void windows_named_condition::wait(L& lock, Pr pred)
-{
- if (!lock)
- throw lock_exception();
- while (!pred())
- this->do_wait(*lock.mutex());
-}
-
-template <typename L>
-inline bool windows_named_condition::timed_wait
- (L& lock, const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock);
- return true;
- }
- if (!lock)
- throw lock_exception();
- return this->do_timed_wait(abs_time, *lock.mutex());
-}
-
-template <typename L, typename Pr>
-inline bool windows_named_condition::timed_wait
- (L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock, pred);
- return true;
- }
- if (!lock)
- throw lock_exception();
-
- while (!pred()){
- if(!this->do_timed_wait(abs_time, *lock.mutex())){
- return pred();
- }
- }
- return true;
-}
-
-inline bool windows_named_condition::remove(const char *name)
-{
- return windows_named_sync::remove(name);
-}
+typedef windows_named_condition_any windows_named_condition;
} //namespace ipcdetail {
} //namespace interprocess {
diff --git a/boost/interprocess/sync/windows/named_condition_any.hpp b/boost/interprocess/sync/windows/named_condition_any.hpp
new file mode 100644
index 0000000000..fc2a7fce61
--- /dev/null
+++ b/boost/interprocess/sync/windows/named_condition_any.hpp
@@ -0,0 +1,240 @@
+ //////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP
+#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/windows/named_sync.hpp>
+#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
+#include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class windows_named_condition_any
+{
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+ //Non-copyable
+ windows_named_condition_any();
+ windows_named_condition_any(const windows_named_condition_any &);
+ windows_named_condition_any &operator=(const windows_named_condition_any &);
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+ public:
+ windows_named_condition_any
+ (create_only_t, const char *name, const permissions &perm)
+ : m_condition_data()
+ {
+ named_cond_callbacks callbacks(m_condition_data.get_members());
+ m_named_sync.open_or_create(DoCreate, name, perm, callbacks);
+ }
+
+ windows_named_condition_any
+ (open_or_create_t, const char *name, const permissions &perm)
+ : m_condition_data()
+ {
+ named_cond_callbacks callbacks(m_condition_data.get_members());
+ m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks);
+ }
+
+ windows_named_condition_any(open_only_t, const char *name)
+ : m_condition_data()
+ {
+ named_cond_callbacks callbacks(m_condition_data.get_members());
+ m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks);
+ }
+
+ ~windows_named_condition_any()
+ {
+ named_cond_callbacks callbacks(m_condition_data.get_members());
+ m_named_sync.close(callbacks);
+ }
+
+ void notify_one()
+ { m_condition_data.notify_one(); }
+
+ void notify_all()
+ { m_condition_data.notify_all(); }
+
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ { return m_condition_data.timed_wait(lock, abs_time); }
+
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ { return m_condition_data.timed_wait(lock, abs_time, pred); }
+
+ template <typename L>
+ void wait(L& lock)
+ { m_condition_data.wait(lock); }
+
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ { m_condition_data.wait(lock, pred); }
+
+ static bool remove(const char *name)
+ { return windows_named_sync::remove(name); }
+
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ private:
+
+ void dont_close_on_destruction()
+ {}
+
+ friend class interprocess_tester;
+
+ struct condition_data
+ {
+ typedef boost::int32_t integer_type;
+ typedef winapi_semaphore_wrapper semaphore_type;
+ typedef winapi_mutex_wrapper mutex_type;
+
+ integer_type &get_nwaiters_blocked()
+ { return m_nwaiters_blocked; }
+
+ integer_type &get_nwaiters_gone()
+ { return m_nwaiters_gone; }
+
+ integer_type &get_nwaiters_to_unblock()
+ { return m_nwaiters_to_unblock; }
+
+ semaphore_type &get_sem_block_queue()
+ { return m_sem_block_queue; }
+
+ semaphore_type &get_sem_block_lock()
+ { return m_sem_block_lock; }
+
+ mutex_type &get_mtx_unblock_lock()
+ { return m_mtx_unblock_lock; }
+
+ integer_type m_nwaiters_blocked;
+ integer_type m_nwaiters_gone;
+ integer_type m_nwaiters_to_unblock;
+ winapi_semaphore_wrapper m_sem_block_queue;
+ winapi_semaphore_wrapper m_sem_block_lock;
+ winapi_mutex_wrapper m_mtx_unblock_lock;
+ };
+
+ class named_cond_callbacks : public windows_named_sync_interface
+ {
+ typedef __int64 sem_count_t;
+ mutable sem_count_t sem_counts [2];
+
+ public:
+ named_cond_callbacks(condition_data &cond_data)
+ : m_condition_data(cond_data)
+ {}
+
+ virtual std::size_t get_data_size() const
+ { return sizeof(sem_counts); }
+
+ virtual const void *buffer_with_final_data_to_file()
+ {
+ sem_counts[0] = m_condition_data.m_sem_block_queue.value();
+ sem_counts[1] = m_condition_data.m_sem_block_lock.value();
+ return &sem_counts;
+ }
+
+ virtual const void *buffer_with_init_data_to_file()
+ {
+ sem_counts[0] = 0;
+ sem_counts[1] = 1;
+ return &sem_counts;
+ }
+
+ virtual void *buffer_to_store_init_data_from_file()
+ { return &sem_counts; }
+
+ virtual bool open(create_enum_t, const char *id_name)
+ {
+ m_condition_data.m_nwaiters_blocked = 0;
+ m_condition_data.m_nwaiters_gone = 0;
+ m_condition_data.m_nwaiters_to_unblock = 0;
+
+ //Now open semaphores and mutex.
+ //Use local variables + swap to guarantee consistent
+ //initialization and cleanup in case any opening fails
+ permissions perm;
+ perm.set_unrestricted();
+ std::string aux_str = "Global\\bipc.cond.";
+ aux_str += id_name;
+ std::size_t pos = aux_str.size();
+
+ //sem_block_queue
+ aux_str += "_bq";
+ winapi_semaphore_wrapper sem_block_queue;
+ bool created;
+ if(!sem_block_queue.open_or_create
+ (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created))
+ return false;
+ aux_str.erase(pos);
+
+ //sem_block_lock
+ aux_str += "_bl";
+ winapi_semaphore_wrapper sem_block_lock;
+ if(!sem_block_lock.open_or_create
+ (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created))
+ return false;
+ aux_str.erase(pos);
+
+ //mtx_unblock_lock
+ aux_str += "_ul";
+ winapi_mutex_wrapper mtx_unblock_lock;
+ if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm))
+ return false;
+
+ //All ok, commit data
+ m_condition_data.m_sem_block_queue.swap(sem_block_queue);
+ m_condition_data.m_sem_block_lock.swap(sem_block_lock);
+ m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock);
+ return true;
+ }
+
+ virtual void close()
+ {
+ m_condition_data.m_sem_block_queue.close();
+ m_condition_data.m_sem_block_lock.close();
+ m_condition_data.m_mtx_unblock_lock.close();
+ m_condition_data.m_nwaiters_blocked = 0;
+ m_condition_data.m_nwaiters_gone = 0;
+ m_condition_data.m_nwaiters_to_unblock = 0;
+ }
+
+ virtual ~named_cond_callbacks()
+ {}
+
+ private:
+ condition_data &m_condition_data;
+ };
+
+ windows_named_sync m_named_sync;
+ ipcdetail::condition_8a_wrapper<condition_data> m_condition_data;
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP
diff --git a/boost/interprocess/sync/windows/named_mutex.hpp b/boost/interprocess/sync/windows/named_mutex.hpp
index 8ea6b3e1e4..9d5738562b 100644
--- a/boost/interprocess/sync/windows/named_mutex.hpp
+++ b/boost/interprocess/sync/windows/named_mutex.hpp
@@ -10,7 +10,7 @@
#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP
#define BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -35,13 +35,13 @@ namespace ipcdetail {
class windows_named_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
windows_named_mutex();
windows_named_mutex(const windows_named_mutex &);
windows_named_mutex &operator=(const windows_named_mutex &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
windows_named_mutex(create_only_t, const char *name, const permissions &perm = permissions());
@@ -59,7 +59,7 @@ class windows_named_mutex
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class interprocess_tester;
void dont_close_on_destruction();
@@ -106,7 +106,7 @@ class windows_named_mutex
private:
winapi_mutex_wrapper& m_mtx_wrapper;
};
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
inline windows_named_mutex::~windows_named_mutex()
diff --git a/boost/interprocess/sync/windows/named_recursive_mutex.hpp b/boost/interprocess/sync/windows/named_recursive_mutex.hpp
index cb2ef79ac1..695c44a5a9 100644
--- a/boost/interprocess/sync/windows/named_recursive_mutex.hpp
+++ b/boost/interprocess/sync/windows/named_recursive_mutex.hpp
@@ -10,7 +10,7 @@
#ifndef BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP
#define BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -27,13 +27,13 @@ class windows_named_recursive_mutex
//Windows mutexes based on CreateMutex are already recursive...
: public windows_named_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
windows_named_recursive_mutex();
windows_named_recursive_mutex(const windows_named_mutex &);
windows_named_recursive_mutex &operator=(const windows_named_mutex &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
windows_named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions())
diff --git a/boost/interprocess/sync/windows/named_semaphore.hpp b/boost/interprocess/sync/windows/named_semaphore.hpp
index 8f48d4df96..7adf91b751 100644
--- a/boost/interprocess/sync/windows/named_semaphore.hpp
+++ b/boost/interprocess/sync/windows/named_semaphore.hpp
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP
#define BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -32,13 +32,13 @@ namespace ipcdetail {
class windows_named_semaphore
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
windows_named_semaphore();
windows_named_semaphore(const windows_named_semaphore &);
windows_named_semaphore &operator=(const windows_named_semaphore &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
windows_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions());
@@ -56,7 +56,7 @@ class windows_named_semaphore
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class interprocess_tester;
void dont_close_on_destruction();
@@ -109,7 +109,7 @@ class windows_named_semaphore
winapi_semaphore_wrapper& m_sem_wrapper;
};
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
inline windows_named_semaphore::~windows_named_semaphore()
diff --git a/boost/interprocess/sync/windows/named_sync.hpp b/boost/interprocess/sync/windows/named_sync.hpp
index 41f299f8eb..5af7a3221a 100644
--- a/boost/interprocess/sync/windows/named_sync.hpp
+++ b/boost/interprocess/sync/windows/named_sync.hpp
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP
#define BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -19,12 +19,12 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/permissions.hpp>
-#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/detail/shared_dir_helpers.hpp>
#include <boost/interprocess/sync/windows/sync_utils.hpp>
#include <boost/interprocess/errors.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <string>
-#include <cassert>
+#include <boost/assert.hpp>
namespace boost {
namespace interprocess {
@@ -47,12 +47,12 @@ inline windows_named_sync_interface::~windows_named_sync_interface()
class windows_named_sync
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
windows_named_sync(const windows_named_sync &);
windows_named_sync &operator=(const windows_named_sync &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
windows_named_sync();
@@ -61,11 +61,11 @@ class windows_named_sync
static bool remove(const char *name);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
void *m_file_hnd;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
inline windows_named_sync::windows_named_sync()
@@ -106,7 +106,7 @@ inline void windows_named_sync::open_or_create
//Use a file to emulate POSIX lifetime semantics. After this logic
//we'll obtain the ID of the native handle to open in aux_str
{
- create_tmp_and_clean_old_and_get_filename(name, aux_str);
+ create_shared_dir_cleaning_old_and_get_filepath(name, aux_str);
//Create a file with required permissions.
m_file_hnd = winapi::create_file
( aux_str.c_str()
@@ -145,7 +145,7 @@ inline void windows_named_sync::open_or_create
success = true;
}
winapi::get_file_size(m_file_hnd, filesize);
- assert(std::size_t(filesize) == sizeof_file_info);
+ BOOST_ASSERT(std::size_t(filesize) == sizeof_file_info);
}
else{
void *buf = sync_interface.buffer_to_store_init_data_from_file();
@@ -198,7 +198,7 @@ inline bool windows_named_sync::remove(const char *name)
try{
//Make sure a temporary path is created for shared memory
std::string semfile;
- ipcdetail::tmp_filename(name, semfile);
+ ipcdetail::shared_filepath(name, semfile);
return winapi::unlink_file(semfile.c_str());
}
catch(...){
diff --git a/boost/interprocess/sync/windows/recursive_mutex.hpp b/boost/interprocess/sync/windows/recursive_mutex.hpp
index 9565cb6fb4..55a838583b 100644
--- a/boost/interprocess/sync/windows/recursive_mutex.hpp
+++ b/boost/interprocess/sync/windows/recursive_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP
#define BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/interprocess/sync/windows/semaphore.hpp b/boost/interprocess/sync/windows/semaphore.hpp
index af336df48a..7fdbc41b3d 100644
--- a/boost/interprocess/sync/windows/semaphore.hpp
+++ b/boost/interprocess/sync/windows/semaphore.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP
#define BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -23,6 +23,7 @@
#include <boost/interprocess/sync/windows/sync_utils.hpp>
#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
#include <boost/interprocess/exceptions.hpp>
+#include <boost/assert.hpp>
namespace boost {
@@ -56,8 +57,8 @@ inline windows_semaphore::windows_semaphore(unsigned int initialCount)
bool open_or_created;
handles.obtain_semaphore(this->id_, initialCount, &open_or_created);
//The semaphore must be created, never opened
- assert(open_or_created);
- assert(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
+ BOOST_ASSERT(open_or_created);
+ BOOST_ASSERT(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
(void)open_or_created;
}
diff --git a/boost/interprocess/sync/windows/sync_utils.hpp b/boost/interprocess/sync/windows/sync_utils.hpp
index 0281da1266..7e54cc36b2 100644
--- a/boost/interprocess/sync/windows/sync_utils.hpp
+++ b/boost/interprocess/sync/windows/sync_utils.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
#define BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -23,7 +23,13 @@
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
-#include <boost/unordered/unordered_map.hpp>
+
+//Shield against external warnings
+#include <boost/interprocess/detail/config_external_begin.hpp>
+ #include <boost/unordered/unordered_map.hpp>
+#include <boost/interprocess/detail/config_external_end.hpp>
+
+
#include <boost/container/map.hpp>
#include <cstddef>
@@ -71,7 +77,7 @@ class sync_id
internal_type &internal_pod()
{ return rand_; }
- const void *map_addr() const
+ const void *map_address() const
{ return map_addr_; }
friend std::size_t hash_value(const sync_id &m)
@@ -94,7 +100,7 @@ class sync_handles
struct address_less
{
bool operator()(sync_id const * const l, sync_id const * const r) const
- { return l->map_addr() < r->map_addr(); }
+ { return l->map_address() < r->map_address(); }
};
typedef boost::unordered_map<sync_id, void*> umap_type;
@@ -156,12 +162,15 @@ class sync_handles
umap_type::value_type v(id, (void*)0);
scoped_lock<spin_mutex> lock(mtx_);
umap_type::iterator it = umap_.insert(v).first;
- map_[&it->first] = it;
void *&hnd_val = it->second;
if(!hnd_val){
+ map_[&it->first] = it;
hnd_val = open_or_create_mutex(id);
if(popen_created) *popen_created = true;
}
+ else if(popen_created){
+ *popen_created = false;
+ }
return hnd_val;
}
@@ -170,12 +179,15 @@ class sync_handles
umap_type::value_type v(id, (void*)0);
scoped_lock<spin_mutex> lock(mtx_);
umap_type::iterator it = umap_.insert(v).first;
- map_[&it->first] = it;
void *&hnd_val = it->second;
if(!hnd_val){
+ map_[&it->first] = it;
hnd_val = open_or_create_semaphore(id, initial_count);
if(popen_created) *popen_created = true;
}
+ else if(popen_created){
+ *popen_created = false;
+ }
return hnd_val;
}
@@ -195,13 +207,13 @@ class sync_handles
void destroy_syncs_in_range(const void *addr, std::size_t size)
{
- sync_id low_id(addr);
- sync_id hig_id(static_cast<const char*>(addr)+size);
+ const sync_id low_id(addr);
+ const sync_id hig_id(static_cast<const char*>(addr)+size);
scoped_lock<spin_mutex> lock(mtx_);
map_type::iterator itlow(map_.lower_bound(&low_id)),
ithig(map_.lower_bound(&hig_id));
while(itlow != ithig){
- void *hnd = umap_[*itlow->first];
+ void * const hnd = umap_[*itlow->first];
winapi::close_handle(hnd);
umap_.erase(*itlow->first);
itlow = map_.erase(itlow);
diff --git a/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp b/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp
index 0be96011cf..f7b78a9260 100644
--- a/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp
+++ b/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP
#define BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -21,6 +21,7 @@
#include <boost/interprocess/permissions.hpp>
#include <boost/interprocess/detail/win32_api.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/windows/winapi_wrapper_common.hpp>
#include <boost/interprocess/errors.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <limits>
@@ -31,12 +32,12 @@ namespace ipcdetail {
class winapi_mutex_functions
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
winapi_mutex_functions(const winapi_mutex_functions &);
winapi_mutex_functions &operator=(const winapi_mutex_functions &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
winapi_mutex_functions(void *mtx_hnd)
@@ -44,73 +45,39 @@ class winapi_mutex_functions
{}
void unlock()
- {
- winapi::release_mutex(m_mtx_hnd);
- }
+ { winapi::release_mutex(m_mtx_hnd); }
void lock()
- {
- if(winapi::wait_for_single_object(m_mtx_hnd, winapi::infinite_time) != winapi::wait_object_0){
- error_info err = system_error_code();
- throw interprocess_exception(err);
- }
- }
+ { return winapi_wrapper_wait_for_single_object(m_mtx_hnd); }
bool try_lock()
- {
- unsigned long ret = winapi::wait_for_single_object(m_mtx_hnd, 0);
- if(ret == winapi::wait_object_0){
- return true;
- }
- else if(ret == winapi::wait_timeout){
- return false;
- }
- else{
- error_info err = system_error_code();
- throw interprocess_exception(err);
- }
- }
+ { return winapi_wrapper_try_wait_for_single_object(m_mtx_hnd); }
bool timed_lock(const boost::posix_time::ptime &abs_time)
- {
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
+ { return winapi_wrapper_timed_wait_for_single_object(m_mtx_hnd, abs_time); }
- unsigned long ret = winapi::wait_for_single_object
- (m_mtx_hnd, (abs_time - microsec_clock::universal_time()).total_milliseconds());
- if(ret == winapi::wait_object_0){
- return true;
- }
- else if(ret == winapi::wait_timeout){
- return false;
- }
- else{
- error_info err = system_error_code();
- throw interprocess_exception(err);
- }
- }
-
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
protected:
void *m_mtx_hnd;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//Swappable mutex wrapper
class winapi_mutex_wrapper
: public winapi_mutex_functions
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
winapi_mutex_wrapper(const winapi_mutex_wrapper &);
winapi_mutex_wrapper &operator=(const winapi_mutex_wrapper &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+ //Note that Windows API does not return winapi::invalid_handle_value
+ //when failing to create/open a mutex, but a nullptr
public:
- winapi_mutex_wrapper(void *mtx_hnd = winapi::invalid_handle_value)
+ winapi_mutex_wrapper(void *mtx_hnd = 0)
: winapi_mutex_functions(mtx_hnd)
{}
@@ -120,7 +87,7 @@ class winapi_mutex_wrapper
void *release()
{
void *hnd = m_mtx_hnd;
- m_mtx_hnd = winapi::invalid_handle_value;
+ m_mtx_hnd = 0;
return hnd;
}
@@ -129,24 +96,24 @@ class winapi_mutex_wrapper
bool open_or_create(const char *name, const permissions &perm)
{
- if(m_mtx_hnd == winapi::invalid_handle_value){
+ if(m_mtx_hnd == 0){
m_mtx_hnd = winapi::open_or_create_mutex
( name
, false
, (winapi::interprocess_security_attributes*)perm.get_permissions()
);
- return m_mtx_hnd != winapi::invalid_handle_value;
+ return m_mtx_hnd != 0;
}
else{
return false;
}
- }
+ }
void close()
{
- if(m_mtx_hnd != winapi::invalid_handle_value){
+ if(m_mtx_hnd != 0){
winapi::close_handle(m_mtx_hnd);
- m_mtx_hnd = winapi::invalid_handle_value;
+ m_mtx_hnd = 0;
}
}
diff --git a/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp b/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp
index 2dd7845627..f64d506d4d 100644
--- a/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp
+++ b/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP
#define BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -21,6 +21,7 @@
#include <boost/interprocess/permissions.hpp>
#include <boost/interprocess/detail/win32_api.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/windows/winapi_wrapper_common.hpp>
#include <boost/interprocess/errors.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <limits>
@@ -31,12 +32,12 @@ namespace ipcdetail {
class winapi_semaphore_functions
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable
winapi_semaphore_functions(const winapi_semaphore_functions &);
winapi_semaphore_functions &operator=(const winapi_semaphore_functions &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
winapi_semaphore_functions(void *hnd)
@@ -50,69 +51,34 @@ class winapi_semaphore_functions
}
void wait()
- {
- if(winapi::wait_for_single_object(m_sem_hnd, winapi::infinite_time) != winapi::wait_object_0){
- error_info err = system_error_code();
- throw interprocess_exception(err);
- }
- }
+ { return winapi_wrapper_wait_for_single_object(m_sem_hnd); }
bool try_wait()
- {
- unsigned long ret = winapi::wait_for_single_object(m_sem_hnd, 0);
- if(ret == winapi::wait_object_0){
- return true;
- }
- else if(ret == winapi::wait_timeout){
- return false;
- }
- else{
- error_info err = system_error_code();
- throw interprocess_exception(err);
- }
- }
+ { return winapi_wrapper_try_wait_for_single_object(m_sem_hnd); }
bool timed_wait(const boost::posix_time::ptime &abs_time)
- {
- if(abs_time == boost::posix_time::pos_infin){
- this->wait();
- return true;
- }
-
- unsigned long ret = winapi::wait_for_single_object
- (m_sem_hnd, (abs_time - microsec_clock::universal_time()).total_milliseconds());
- if(ret == winapi::wait_object_0){
- return true;
- }
- else if(ret == winapi::wait_timeout){
- return false;
- }
- else{
- error_info err = system_error_code();
- throw interprocess_exception(err);
- }
- }
+ { return winapi_wrapper_timed_wait_for_single_object(m_sem_hnd, abs_time); }
long value() const
{
- long count, limit;
- if(!winapi::get_semaphore_info(m_sem_hnd, count, limit))
+ long l_count, l_limit;
+ if(!winapi::get_semaphore_info(m_sem_hnd, l_count, l_limit))
return 0;
- return count;
+ return l_count;
}
long limit() const
{
- long count, limit;
- if(!winapi::get_semaphore_info(m_sem_hnd, count, limit))
+ long l_count, l_limit;
+ if(!winapi::get_semaphore_info(m_sem_hnd, l_count, l_limit))
return 0;
- return limit;
+ return l_limit;
}
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
protected:
void *m_sem_hnd;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
@@ -136,7 +102,7 @@ class winapi_semaphore_wrapper
{ this->close(); }
void *release()
- {
+ {
void *hnd = m_sem_hnd;
m_sem_hnd = winapi::invalid_handle_value;
return hnd;
diff --git a/boost/interprocess/sync/windows/winapi_wrapper_common.hpp b/boost/interprocess/sync/windows/winapi_wrapper_common.hpp
new file mode 100644
index 0000000000..ccf2d65cb6
--- /dev/null
+++ b/boost/interprocess/sync/windows/winapi_wrapper_common.hpp
@@ -0,0 +1,93 @@
+ //////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WINAPI_WRAPPER_COMMON_HPP
+#define BOOST_INTERPROCESS_DETAIL_WINAPI_WRAPPER_COMMON_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/win32_api.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/errors.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <limits>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+inline void winapi_wrapper_wait_for_single_object(void *handle)
+{
+ unsigned long ret = winapi::wait_for_single_object(handle, winapi::infinite_time);
+ if(ret != winapi::wait_object_0){
+ if(ret != winapi::wait_abandoned){
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+ else{ //Special case for orphaned mutexes
+ winapi::release_mutex(handle);
+ throw interprocess_exception(owner_dead_error);
+ }
+ }
+}
+
+inline bool winapi_wrapper_try_wait_for_single_object(void *handle)
+{
+ unsigned long ret = winapi::wait_for_single_object(handle, 0);
+ if(ret == winapi::wait_object_0){
+ return true;
+ }
+ else if(ret == winapi::wait_timeout){
+ return false;
+ }
+ else{
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+}
+
+inline bool winapi_wrapper_timed_wait_for_single_object(void *handle, const boost::posix_time::ptime &abs_time)
+{
+ //Windows does not support infinity abs_time so check it
+ if(abs_time == boost::posix_time::pos_infin){
+ winapi_wrapper_wait_for_single_object(handle);
+ return true;
+ }
+ const boost::posix_time::ptime cur_time = microsec_clock::universal_time();
+ //Windows uses relative wait times so check for negative waits
+ //and implement as 0 wait to allow try-semantics as POSIX mandates.
+ unsigned long ret = winapi::wait_for_single_object
+ ( handle
+ , (abs_time <= cur_time) ? 0u
+ : (abs_time - cur_time).total_milliseconds()
+ );
+ if(ret == winapi::wait_object_0){
+ return true;
+ }
+ else if(ret == winapi::wait_timeout){
+ return false;
+ }
+ else{
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP
diff --git a/boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp b/boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp
index a0c3a91adf..b69cfbf934 100644
--- a/boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp
+++ b/boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp
@@ -30,6 +30,10 @@
#ifndef BOOST_INTERPROCESS_SYNC_XSI_ADVANCED_XSI_SEMAPHORE_HPP
#define BOOST_INTERPROCESS_SYNC_XSI_ADVANCED_XSI_SEMAPHORE_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
diff --git a/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp b/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp
index 266e7c5dac..69ad34caf2 100644
--- a/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp
+++ b/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -10,6 +10,10 @@
#ifndef BOOST_INTERPROCESS_SYNC_XSI_SIMPLE_XSI_SEMAPHORE_HPP
#define BOOST_INTERPROCESS_SYNC_XSI_SIMPLE_XSI_SEMAPHORE_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
/*
* Provide an simpler and easier to understand interface to the System V
* semaphore system calls. There are 7 routines available to the user:
diff --git a/boost/interprocess/sync/xsi/xsi_named_mutex.hpp b/boost/interprocess/sync/xsi/xsi_named_mutex.hpp
index 485b1ac101..1c4ee78a4f 100644
--- a/boost/interprocess/sync/xsi/xsi_named_mutex.hpp
+++ b/boost/interprocess/sync/xsi/xsi_named_mutex.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP
#define BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
@@ -18,7 +22,7 @@
#error "This header can't be used in Windows operating systems"
#endif
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/utilities.hpp>
@@ -42,11 +46,11 @@ namespace interprocess {
//!that undoes the operation if the process crashes.
class xsi_named_mutex
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable and non-assignable
xsi_named_mutex(xsi_named_mutex &);
xsi_named_mutex &operator=(xsi_named_mutex &);
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_named_mutex)
@@ -72,10 +76,10 @@ class xsi_named_mutex
//!After the call, "moved" does not represent any named mutex.
//!Does not throw
xsi_named_mutex &operator=(BOOST_RV_REF(xsi_named_mutex) moved)
- {
+ {
xsi_named_mutex tmp(boost::move(moved));
this->swap(tmp);
- return *this;
+ return *this;
}
//!Swaps two xsi_named_mutex. Does not throw
@@ -105,7 +109,7 @@ class xsi_named_mutex
void unlock();
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
//!Closes a previously opened file mapping. Never throws.
@@ -121,10 +125,10 @@ class xsi_named_mutex
boost::uint8_t m_id;
int m_perm;
std::string m_path;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline xsi_named_mutex::xsi_named_mutex()
: m_semid(-1), m_key(-1), m_id(0), m_perm(0), m_path()
@@ -142,7 +146,7 @@ inline void xsi_named_mutex::swap(xsi_named_mutex &other)
std::swap(m_id, other.m_id);
std::swap(m_semid, other.m_semid);
std::swap(m_perm, other.m_perm);
- m_path.swap(other.m_path);
+ m_path.swap(other.m_path);
}
inline mapping_handle_t xsi_named_mutex::get_mapping_handle() const
@@ -218,7 +222,7 @@ inline bool xsi_named_mutex::remove()
return false;
}
-///@endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/windows_shared_memory.hpp b/boost/interprocess/windows_shared_memory.hpp
index 76601bb363..5898b4b113 100644
--- a/boost/interprocess/windows_shared_memory.hpp
+++ b/boost/interprocess/windows_shared_memory.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP
#define BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/detail/workaround.hpp>
@@ -50,23 +54,23 @@ namespace interprocess {
//!can't communicate between them.
class windows_shared_memory
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable and non-assignable
BOOST_MOVABLE_BUT_NOT_COPYABLE(windows_shared_memory)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Default constructor.
//!Represents an empty windows_shared_memory.
windows_shared_memory();
- //!Creates a new native shared memory with name "name" and mode "mode",
+ //!Creates a new native shared memory with name "name" and at least size "size",
//!with the access mode "mode".
//!If the file previously exists, throws an error.
windows_shared_memory(create_only_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions())
{ this->priv_open_or_create(ipcdetail::DoCreate, name, mode, size, perm); }
- //!Tries to create a shared memory object with name "name" and mode "mode", with the
+ //!Tries to create a shared memory object with name "name" and at least size "size", with the
//!access mode "mode". If the file previously exists, it tries to open it with mode "mode".
//!Otherwise throws an error.
windows_shared_memory(open_or_create_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions())
@@ -88,10 +92,10 @@ class windows_shared_memory
//!After the call, "moved" does not represent any shared memory.
//!Does not throw
windows_shared_memory &operator=(BOOST_RV_REF(windows_shared_memory) moved)
- {
+ {
windows_shared_memory tmp(boost::move(moved));
this->swap(tmp);
- return *this;
+ return *this;
}
//!Swaps to shared_memory_objects. Does not throw
@@ -112,7 +116,11 @@ class windows_shared_memory
//!Returns the mapping handle. Never throws
mapping_handle_t get_mapping_handle() const;
- /// @cond
+ //!Returns the size of the windows shared memory. It will be a 4K rounded
+ //!size of the "size" passed in the constructor.
+ offset_t get_size() const;
+
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
//!Closes a previously opened file mapping. Never throws.
@@ -124,10 +132,10 @@ class windows_shared_memory
void * m_handle;
mode_t m_mode;
std::string m_name;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline windows_shared_memory::windows_shared_memory()
: m_handle(0)
@@ -140,10 +148,10 @@ inline const char *windows_shared_memory::get_name() const
{ return m_name.c_str(); }
inline void windows_shared_memory::swap(windows_shared_memory &other)
-{
+{
std::swap(m_handle, other.m_handle);
std::swap(m_mode, other.m_mode);
- m_name.swap(other.m_name);
+ m_name.swap(other.m_name);
}
inline mapping_handle_t windows_shared_memory::get_mapping_handle() const
@@ -152,6 +160,12 @@ inline mapping_handle_t windows_shared_memory::get_mapping_handle() const
inline mode_t windows_shared_memory::get_mode() const
{ return m_mode; }
+inline offset_t windows_shared_memory::get_size() const
+{
+ offset_t size; //This shall never fail
+ return (m_handle && winapi::get_file_mapping_size(m_handle, size)) ? size : 0;
+}
+
inline bool windows_shared_memory::priv_open_or_create
(ipcdetail::create_enum_t type, const char *filename, mode_t mode, std::size_t size, const permissions& perm)
{
@@ -223,7 +237,7 @@ inline void windows_shared_memory::priv_close()
}
}
-///@endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {
diff --git a/boost/interprocess/xsi_key.hpp b/boost/interprocess/xsi_key.hpp
index ffd4c498df..38e990a57e 100644
--- a/boost/interprocess/xsi_key.hpp
+++ b/boost/interprocess/xsi_key.hpp
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_XSI_KEY_HPP
#define BOOST_INTERPROCESS_XSI_KEY_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/detail/workaround.hpp>
@@ -22,7 +26,7 @@
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/utilities.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -55,7 +59,7 @@ class xsi_key
//!If the shared memory previously exists, throws an error.
xsi_key(const char *path, boost::uint8_t id)
{
- key_t key;
+ key_t key;
if(path){
key = ::ftok(path, id);
if(((key_t)-1) == key){
@@ -73,10 +77,10 @@ class xsi_key
key_t get_key() const
{ return m_key; }
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
key_t m_key;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
} //namespace interprocess {
diff --git a/boost/interprocess/xsi_shared_memory.hpp b/boost/interprocess/xsi_shared_memory.hpp
index e84d9b1c54..3451717d0b 100644
--- a/boost/interprocess/xsi_shared_memory.hpp
+++ b/boost/interprocess/xsi_shared_memory.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_HPP
#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/detail/workaround.hpp>
@@ -22,7 +26,7 @@
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/utilities.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -47,10 +51,10 @@ namespace interprocess {
//!can't communicate between them.
class xsi_shared_memory
{
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Non-copyable and non-assignable
BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory)
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Default constructor.
@@ -89,10 +93,10 @@ class xsi_shared_memory
//!After the call, "moved" does not represent any shared memory.
//!Does not throw
xsi_shared_memory &operator=(BOOST_RV_REF(xsi_shared_memory) moved)
- {
+ {
xsi_shared_memory tmp(boost::move(moved));
this->swap(tmp);
- return *this;
+ return *this;
}
//!Swaps two xsi_shared_memorys. Does not throw
@@ -115,7 +119,7 @@ class xsi_shared_memory
//!Returns false on error. Never throws
static bool remove(int shmid);
- /// @cond
+ #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
//!Closes a previously opened file mapping. Never throws.
@@ -124,10 +128,10 @@ class xsi_shared_memory
, const permissions& perm
, std::size_t size);
int m_shmid;
- /// @endcond
+ #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
-/// @cond
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline xsi_shared_memory::xsi_shared_memory()
: m_shmid(-1)
@@ -191,7 +195,7 @@ inline bool xsi_shared_memory::priv_open_or_create
inline bool xsi_shared_memory::remove(int shmid)
{ return -1 != ::shmctl(shmid, IPC_RMID, 0); }
-///@endcond
+#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {
} //namespace boost {