diff options
Diffstat (limited to 'boost/interprocess')
123 files changed, 5839 insertions, 3836 deletions
diff --git a/boost/interprocess/allocators/adaptive_pool.hpp b/boost/interprocess/allocators/adaptive_pool.hpp index 846df5d413..a85202b4ee 100644 --- a/boost/interprocess/allocators/adaptive_pool.hpp +++ b/boost/interprocess/allocators/adaptive_pool.hpp @@ -35,7 +35,7 @@ #include <cstddef> //!\file -//!Describes adaptive_pool pooled shared memory STL compatible allocator +//!Describes adaptive_pool pooled shared memory STL compatible allocator namespace boost { namespace interprocess { @@ -101,11 +101,11 @@ class adaptive_pool_base typedef boost::container::container_detail::transform_multiallocation_chain <typename SegmentManager::multiallocation_chain, T>multiallocation_chain; - //!Obtains adaptive_pool_base from + //!Obtains adaptive_pool_base from //!adaptive_pool_base template<class T2> struct rebind - { + { typedef adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -122,15 +122,15 @@ class adaptive_pool_base //!Constructor from a segment manager. If not present, constructs a node //!pool. Increments the reference count of the associated node pool. //!Can throw boost::interprocess::bad_alloc - adaptive_pool_base(segment_manager *segment_mngr) + adaptive_pool_base(segment_manager *segment_mngr) : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::type>(segment_mngr)) { } - //!Copy constructor from other adaptive_pool_base. Increments the reference + //!Copy constructor from other adaptive_pool_base. Increments the reference //!count of the associated node pool. Never throws - adaptive_pool_base(const adaptive_pool_base &other) - : mp_node_pool(other.get_node_pool()) - { - node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); + adaptive_pool_base(const adaptive_pool_base &other) + : mp_node_pool(other.get_node_pool()) + { + node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); } //!Assignment from other adaptive_pool_base @@ -151,7 +151,7 @@ class adaptive_pool_base //!Destructor, removes node_pool_t from memory //!if its reference count reaches to zero. Never throws - ~adaptive_pool_base() + ~adaptive_pool_base() { ipcdetail::destroy_node_pool_if_last_link(node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))); } //!Returns a pointer to the node pool. @@ -178,14 +178,14 @@ class adaptive_pool_base //!Equality test for same type //!of adaptive_pool_base template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline -bool operator==(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1, +bool operator==(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1, const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2) { return alloc1.get_node_pool() == alloc2.get_node_pool(); } //!Inequality test for same type //!of adaptive_pool_base template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline -bool operator!=(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1, +bool operator!=(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1, const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2) { return alloc1.get_node_pool() != alloc2.get_node_pool(); } @@ -211,11 +211,11 @@ class adaptive_pool_v1 template<class T2> struct rebind - { + { typedef adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; - adaptive_pool_v1(SegmentManager *segment_mngr) + adaptive_pool_v1(SegmentManager *segment_mngr) : base_t(segment_mngr) {} @@ -230,13 +230,13 @@ class adaptive_pool_v1 /// @endcond -//!An STL node allocator that uses a segment manager as memory +//!An STL node allocator that uses a segment manager as memory //!source. The internal pointer type will of the same type (raw, smart) as //!"typename SegmentManager::void_pointer" type. This allows //!placing the allocator in shared memory, memory mapped-files, etc... //! -//!This node allocator shares a segregated storage between all instances -//!of adaptive_pool with equal sizeof(T) placed in the same segment +//!This node allocator shares a segregated storage between all instances +//!of adaptive_pool with equal sizeof(T) placed in the same segment //!group. NodesPerBlock is the number of nodes allocated at once when the allocator //!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks //!that the adaptive node pool will hold. The rest of the totally free blocks will be @@ -271,11 +271,11 @@ class adaptive_pool template<class T2> struct rebind - { + { typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; - adaptive_pool(SegmentManager *segment_mngr) + adaptive_pool(SegmentManager *segment_mngr) : base_t(segment_mngr) {} @@ -299,11 +299,11 @@ class adaptive_pool typedef typename segment_manager::size_type size_type; typedef typename segment_manager::difference_type difference_type; - //!Obtains adaptive_pool from + //!Obtains adaptive_pool from //!adaptive_pool template<class T2> struct rebind - { + { typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -314,7 +314,7 @@ class adaptive_pool adaptive_pool& operator= (const adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&); - //!Not assignable from + //!Not assignable from //!other adaptive_pool //adaptive_pool& operator=(const adaptive_pool&); @@ -324,7 +324,7 @@ class adaptive_pool //!Can throw boost::interprocess::bad_alloc adaptive_pool(segment_manager *segment_mngr); - //!Copy constructor from other adaptive_pool. Increments the reference + //!Copy constructor from other adaptive_pool. Increments the reference //!count of the associated node pool. Never throws adaptive_pool(const adaptive_pool &other); @@ -351,7 +351,7 @@ class adaptive_pool //!Never throws size_type max_size() const; - //!Allocate memory for an array of count elements. + //!Allocate memory for an array of count elements. //!Throws boost::interprocess::bad_alloc if there is no enough memory pointer allocate(size_type count, cvoid_pointer hint = 0); @@ -375,7 +375,7 @@ class adaptive_pool //!Never throws const_pointer address(const_reference value) const; /* - //!Copy construct an object. + //!Copy construct an object. //!Throws if T's copy constructor throws void construct(const pointer &ptr, const_reference v); @@ -390,7 +390,7 @@ class adaptive_pool std::pair<pointer, bool> allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, + size_type limit_size, size_type preferred_size, size_type &received_size, const pointer &reuse = 0); @@ -448,13 +448,13 @@ class adaptive_pool //!Equality test for same type //!of adaptive_pool template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline -bool operator==(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, +bool operator==(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2); //!Inequality test for same type //!of adaptive_pool template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline -bool operator!=(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, +bool operator!=(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2); #endif diff --git a/boost/interprocess/allocators/allocator.hpp b/boost/interprocess/allocators/allocator.hpp index aa4b22dcc9..38e8c6901a 100644 --- a/boost/interprocess/allocators/allocator.hpp +++ b/boost/interprocess/allocators/allocator.hpp @@ -45,12 +45,12 @@ namespace boost { namespace interprocess { -//!An STL compatible allocator that uses a segment manager as +//!An STL compatible allocator that uses a segment manager as //!memory source. The internal pointer type will of the same type (raw, smart) as //!"typename SegmentManager::void_pointer" type. This allows //!placing the allocator in shared memory, memory mapped-files, etc... template<class T, class SegmentManager> -class allocator +class allocator { public: //Segment manager @@ -115,7 +115,7 @@ class allocator //!objects of type T2 template<class T2> struct rebind - { + { typedef allocator<T2, SegmentManager> other; }; @@ -126,21 +126,21 @@ class allocator //!Constructor from the segment manager. //!Never throws - allocator(segment_manager *segment_mngr) + allocator(segment_manager *segment_mngr) : mp_mngr(segment_mngr) { } //!Constructor from other allocator. //!Never throws - allocator(const allocator &other) + allocator(const allocator &other) : mp_mngr(other.get_segment_manager()){ } //!Constructor from related allocator. //!Never throws template<class T2> - allocator(const allocator<T2, SegmentManager> &other) + allocator(const allocator<T2, SegmentManager> &other) : mp_mngr(other.get_segment_manager()){} - //!Allocates memory for an array of count elements. + //!Allocates memory for an array of count elements. //!Throws boost::interprocess::bad_alloc if there is no enough memory pointer allocate(size_type count, cvoid_ptr hint = 0) { @@ -169,13 +169,13 @@ 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); } std::pair<pointer, bool> allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, + size_type limit_size, size_type preferred_size, size_type &received_size, const pointer &reuse = 0) { @@ -273,14 +273,14 @@ class allocator //!Equality test for same type //!of allocator template<class T, class SegmentManager> inline -bool operator==(const allocator<T , SegmentManager> &alloc1, +bool operator==(const allocator<T , SegmentManager> &alloc1, const allocator<T, SegmentManager> &alloc2) { return alloc1.get_segment_manager() == alloc2.get_segment_manager(); } //!Inequality test for same type //!of allocator template<class T, class SegmentManager> inline -bool operator!=(const allocator<T, SegmentManager> &alloc1, +bool operator!=(const allocator<T, SegmentManager> &alloc1, const allocator<T, SegmentManager> &alloc2) { return alloc1.get_segment_manager() != alloc2.get_segment_manager(); } diff --git a/boost/interprocess/allocators/cached_adaptive_pool.hpp b/boost/interprocess/allocators/cached_adaptive_pool.hpp index bec1050de5..98af033fe6 100644 --- a/boost/interprocess/allocators/cached_adaptive_pool.hpp +++ b/boost/interprocess/allocators/cached_adaptive_pool.hpp @@ -28,7 +28,7 @@ #include <cstddef> //!\file -//!Describes cached_adaptive_pool pooled shared memory STL compatible allocator +//!Describes cached_adaptive_pool pooled shared memory STL compatible allocator namespace boost { namespace interprocess { @@ -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; }; @@ -77,7 +77,7 @@ class cached_adaptive_pool_v1 typedef typename base_t::size_type size_type; cached_adaptive_pool_v1(SegmentManager *segment_mngr, - size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) : base_t(segment_mngr, max_cached_nodes) {} @@ -93,12 +93,12 @@ class cached_adaptive_pool_v1 /// @endcond -//!An STL node allocator that uses a segment manager as memory +//!An STL node allocator that uses a segment manager as memory //!source. The internal pointer type will of the same type (raw, smart) as //!"typename SegmentManager::void_pointer" type. This allows //!placing the allocator in shared memory, memory mapped-files, etc... //! -//!This node allocator shares a segregated storage between all instances of +//!This node allocator shares a segregated storage between all instances of //!cached_adaptive_pool with equal sizeof(T) placed in the same //!memory segment. But also caches some nodes privately to //!avoid some synchronization overhead. @@ -149,13 +149,13 @@ class cached_adaptive_pool template<class T2> struct rebind - { + { typedef cached_adaptive_pool <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; cached_adaptive_pool(SegmentManager *segment_mngr, - std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) : base_t(segment_mngr, max_cached_nodes) {} @@ -179,11 +179,11 @@ class cached_adaptive_pool typedef typename segment_manager::size_type size_type; typedef typename segment_manager::difference_type difference_type; - //!Obtains cached_adaptive_pool from + //!Obtains cached_adaptive_pool from //!cached_adaptive_pool template<class T2> struct rebind - { + { typedef cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -194,7 +194,7 @@ class cached_adaptive_pool cached_adaptive_pool& operator= (const cached_adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&); - //!Not assignable from + //!Not assignable from //!other cached_adaptive_pool cached_adaptive_pool& operator=(const cached_adaptive_pool&); @@ -204,7 +204,7 @@ class cached_adaptive_pool //!Can throw boost::interprocess::bad_alloc cached_adaptive_pool(segment_manager *segment_mngr); - //!Copy constructor from other cached_adaptive_pool. Increments the reference + //!Copy constructor from other cached_adaptive_pool. Increments the reference //!count of the associated node pool. Never throws cached_adaptive_pool(const cached_adaptive_pool &other); @@ -231,7 +231,7 @@ class cached_adaptive_pool //!Never throws size_type max_size() const; - //!Allocate memory for an array of count elements. + //!Allocate memory for an array of count elements. //!Throws boost::interprocess::bad_alloc if there is no enough memory pointer allocate(size_type count, cvoid_pointer hint = 0); @@ -255,7 +255,7 @@ class cached_adaptive_pool //!Never throws const_pointer address(const_reference value) const; - //!Copy construct an object. + //!Copy construct an object. //!Throws if T's copy constructor throws void construct(const pointer &ptr, const_reference v); @@ -270,7 +270,7 @@ class cached_adaptive_pool std::pair<pointer, bool> allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, + size_type limit_size, size_type preferred_size, size_type &received_size, const pointer &reuse = 0); @@ -335,13 +335,13 @@ class cached_adaptive_pool //!Equality test for same type //!of cached_adaptive_pool template<class T, class S, std::size_t NodesPerBlock, std::size_t F, std::size_t OP> inline -bool operator==(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, +bool operator==(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2); //!Inequality test for same type //!of cached_adaptive_pool template<class T, class S, std::size_t NodesPerBlock, std::size_t F, std::size_t OP> inline -bool operator!=(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, +bool operator!=(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2); #endif diff --git a/boost/interprocess/allocators/cached_node_allocator.hpp b/boost/interprocess/allocators/cached_node_allocator.hpp index 03398156db..b0ad0e4ebc 100644 --- a/boost/interprocess/allocators/cached_node_allocator.hpp +++ b/boost/interprocess/allocators/cached_node_allocator.hpp @@ -28,7 +28,7 @@ #include <cstddef> //!\file -//!Describes cached_cached_node_allocator pooled shared memory STL compatible allocator +//!Describes cached_cached_node_allocator pooled shared memory STL compatible allocator namespace boost { namespace interprocess { @@ -64,7 +64,7 @@ class cached_node_allocator_v1 template<class T2> struct rebind - { + { typedef cached_node_allocator_v1 <T2, SegmentManager, NodesPerBlock> other; }; @@ -72,7 +72,7 @@ class cached_node_allocator_v1 typedef typename base_t::size_type size_type; cached_node_allocator_v1(SegmentManager *segment_mngr, - size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) : base_t(segment_mngr, max_cached_nodes) {} @@ -122,12 +122,12 @@ class cached_node_allocator template<class T2> struct rebind - { + { typedef cached_node_allocator<T2, SegmentManager, NodesPerBlock> other; }; cached_node_allocator(SegmentManager *segment_mngr, - size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) : base_t(segment_mngr, max_cached_nodes) {} @@ -151,11 +151,11 @@ class cached_node_allocator typedef typename SegmentManager::size_type size_type; typedef typename SegmentManager::difference_type difference_type; - //!Obtains cached_node_allocator from + //!Obtains cached_node_allocator from //!cached_node_allocator template<class T2> struct rebind - { + { typedef cached_node_allocator<T2, SegmentManager> other; }; @@ -166,7 +166,7 @@ class cached_node_allocator cached_node_allocator& operator= (const cached_node_allocator<T2, SegmentManager2, N2>&); - //!Not assignable from + //!Not assignable from //!other cached_node_allocator cached_node_allocator& operator=(const cached_node_allocator&); @@ -176,7 +176,7 @@ class cached_node_allocator //!Can throw boost::interprocess::bad_alloc cached_node_allocator(segment_manager *segment_mngr); - //!Copy constructor from other cached_node_allocator. Increments the reference + //!Copy constructor from other cached_node_allocator. Increments the reference //!count of the associated node pool. Never throws cached_node_allocator(const cached_node_allocator &other); @@ -203,7 +203,7 @@ class cached_node_allocator //!Never throws size_type max_size() const; - //!Allocate memory for an array of count elements. + //!Allocate memory for an array of count elements. //!Throws boost::interprocess::bad_alloc if there is no enough memory pointer allocate(size_type count, cvoid_pointer hint = 0); @@ -227,7 +227,7 @@ class cached_node_allocator //!Never throws const_pointer address(const_reference value) const; - //!Default construct an object. + //!Default construct an object. //!Throws if T's default constructor throws void construct(const pointer &ptr, const_reference v); @@ -242,7 +242,7 @@ class cached_node_allocator std::pair<pointer, bool> allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, + size_type limit_size, size_type preferred_size, size_type &received_size, const pointer &reuse = 0); @@ -307,13 +307,13 @@ class cached_node_allocator //!Equality test for same type //!of cached_node_allocator template<class T, class S, std::size_t NPC> inline -bool operator==(const cached_node_allocator<T, S, NPC> &alloc1, +bool operator==(const cached_node_allocator<T, S, NPC> &alloc1, const cached_node_allocator<T, S, NPC> &alloc2); //!Inequality test for same type //!of cached_node_allocator template<class T, class S, std::size_t NPC> inline -bool operator!=(const cached_node_allocator<T, S, NPC> &alloc1, +bool operator!=(const cached_node_allocator<T, S, NPC> &alloc1, const cached_node_allocator<T, S, NPC> &alloc2); #endif diff --git a/boost/interprocess/allocators/detail/adaptive_node_pool.hpp b/boost/interprocess/allocators/detail/adaptive_node_pool.hpp index 4ccc920663..abe183146f 100644 --- a/boost/interprocess/allocators/detail/adaptive_node_pool.hpp +++ b/boost/interprocess/allocators/detail/adaptive_node_pool.hpp @@ -74,7 +74,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 @@ -83,7 +83,7 @@ template< class SegmentManager , std::size_t MaxFreeBlocks , unsigned char OverheadPercent > -class shared_adaptive_node_pool +class shared_adaptive_node_pool : public ipcdetail::shared_pool_impl < private_adaptive_node_pool <SegmentManager, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent> diff --git a/boost/interprocess/allocators/detail/allocator_common.hpp b/boost/interprocess/allocators/detail/allocator_common.hpp index ea660b1a90..ba14d3f64d 100644 --- a/boost/interprocess/allocators/detail/allocator_common.hpp +++ b/boost/interprocess/allocators/detail/allocator_common.hpp @@ -73,7 +73,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 +90,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; }; @@ -103,13 +103,13 @@ inline NodePool *get_or_create_node_pool(typename NodePool::segment_manager *mgn return func.mp_node_pool; } -//!Object function that decrements the reference count. If the count -//!reaches to zero destroys the node allocator from memory. +//!Object function that decrements the reference count. If the count +//!reaches to zero destroys the node allocator from memory. //!Never throws template<class NodePool> struct destroy_if_last_link_func { - //!Decrements reference count and destroys the object if there is no + //!Decrements reference count and destroys the object if there is no //!more attached allocators. Never throws void operator()() { @@ -117,19 +117,19 @@ struct destroy_if_last_link_func if(mp_node_pool->dec_ref_count() != 0) return; //Last link, let's destroy the segment_manager - mp_node_pool->get_segment_manager()->template destroy<NodePool>(boost::interprocess::unique_instance); - } + mp_node_pool->get_segment_manager()->template destroy<NodePool>(boost::interprocess::unique_instance); + } //!Constructor. Initializes function //!object parameters - destroy_if_last_link_func(NodePool *pool) + destroy_if_last_link_func(NodePool *pool) : mp_node_pool(pool) {} NodePool *mp_node_pool; }; -//!Destruction function, initializes and executes destruction function +//!Destruction function, initializes and executes destruction function //!object. Never throws template<class NodePool> inline void destroy_node_pool_if_last_link(NodePool *pool) @@ -173,7 +173,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 @@ -227,7 +227,7 @@ class cache_impl //Check if cache is full if(m_cached_nodes.size() >= m_max_cached_nodes){ //This only occurs if this allocator deallocate memory allocated - //with other equal allocator. Since the cache is full, and more + //with other equal allocator. Since the cache is full, and more //deallocations are probably coming, we'll make some room in cache //in a single, efficient multi node deallocation. this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2); @@ -242,7 +242,7 @@ class cache_impl //Check if cache is full if(m_cached_nodes.size() >= m_max_cached_nodes){ //This only occurs if this allocator deallocate memory allocated - //with other equal allocator. Since the cache is full, and more + //with other equal allocator. Since the cache is full, and more //deallocations are probably coming, we'll make some room in cache //in a single, efficient multi node deallocation. this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2); @@ -279,7 +279,7 @@ class cache_impl void priv_deallocate_n_nodes(size_type n) { //This only occurs if this allocator deallocate memory allocated - //with other equal allocator. Since the cache is full, and more + //with other equal allocator. Since the cache is full, and more //deallocations are probably coming, we'll make some room in cache //in a single, efficient multi node deallocation. size_type count(n); @@ -296,10 +296,10 @@ class cache_impl public: void swap(cache_impl &other) { - ipcdetail::do_swap(mp_node_pool, other.mp_node_pool); - m_cached_nodes.swap(other.m_cached_nodes); - ipcdetail::do_swap(m_max_cached_nodes, other.m_max_cached_nodes); - } + ipcdetail::do_swap(mp_node_pool, other.mp_node_pool); + m_cached_nodes.swap(other.m_cached_nodes); + ipcdetail::do_swap(m_max_cached_nodes, other.m_max_cached_nodes); + } }; template<class Derived, class T, class SegmentManager> @@ -335,13 +335,13 @@ 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); } std::pair<pointer, bool> allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, + size_type limit_size, size_type preferred_size, size_type &received_size, const pointer &reuse = 0) { @@ -450,7 +450,7 @@ class node_pool_allocation_impl }; public: - //!Allocate memory for an array of count elements. + //!Allocate memory for an array of count elements. //!Throws boost::interprocess::bad_alloc if there is no enough memory pointer allocate(size_type count, cvoid_pointer hint = 0) { @@ -599,7 +599,7 @@ class cached_allocator_impl size_type get_max_cached_nodes() const { return m_cache.get_max_cached_nodes(); } - //!Allocate memory for an array of count elements. + //!Allocate memory for an array of count elements. //!Throws boost::interprocess::bad_alloc if there is no enough memory pointer allocate(size_type count, cvoid_pointer hint = 0) { @@ -612,7 +612,7 @@ class cached_allocator_impl } else{ ret = this->get_segment_manager()->allocate(sizeof(T)*count); - } + } return pointer(static_cast<T*>(ret)); } @@ -686,20 +686,20 @@ class cached_allocator_impl //!Equality test for same type of //!cached_allocator_impl template<class T, class N, unsigned int V> inline -bool operator==(const cached_allocator_impl<T, N, V> &alloc1, +bool operator==(const cached_allocator_impl<T, N, V> &alloc1, const cached_allocator_impl<T, N, V> &alloc2) { return alloc1.get_node_pool() == alloc2.get_node_pool(); } //!Inequality test for same type of //!cached_allocator_impl template<class T, class N, unsigned int V> inline -bool operator!=(const cached_allocator_impl<T, N, V> &alloc1, +bool operator!=(const cached_allocator_impl<T, N, V> &alloc1, const cached_allocator_impl<T, N, V> &alloc2) { return alloc1.get_node_pool() != alloc2.get_node_pool(); } //!Pooled shared memory allocator using adaptive pool. Includes -//!a reference count but the class does not delete itself, this is +//!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 +736,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) { @@ -756,7 +756,7 @@ class shared_pool_impl return private_node_allocator_t::allocate_nodes(nodes, n); } */ - //!Allocates n nodes. + //!Allocates n nodes. //!Can throw boost::interprocess::bad_alloc multiallocation_chain allocate_nodes(const size_type n) { diff --git a/boost/interprocess/allocators/detail/node_pool.hpp b/boost/interprocess/allocators/detail/node_pool.hpp index 7327ff92d5..562b64863b 100644 --- a/boost/interprocess/allocators/detail/node_pool.hpp +++ b/boost/interprocess/allocators/detail/node_pool.hpp @@ -37,7 +37,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,18 +73,18 @@ 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 , std::size_t NodeSize , std::size_t NodesPerBlock > -class shared_node_pool +class shared_node_pool : public ipcdetail::shared_pool_impl < private_node_pool <SegmentManager, NodeSize, NodesPerBlock> diff --git a/boost/interprocess/allocators/node_allocator.hpp b/boost/interprocess/allocators/node_allocator.hpp index f1c3259d73..2c1fe566a3 100644 --- a/boost/interprocess/allocators/node_allocator.hpp +++ b/boost/interprocess/allocators/node_allocator.hpp @@ -34,7 +34,7 @@ #include <cstddef> //!\file -//!Describes node_allocator pooled shared memory STL compatible allocator +//!Describes node_allocator pooled shared memory STL compatible allocator namespace boost { namespace interprocess { @@ -98,11 +98,11 @@ class node_allocator_base typedef boost::container::container_detail::transform_multiallocation_chain <typename SegmentManager::multiallocation_chain, T>multiallocation_chain; - //!Obtains node_allocator_base from + //!Obtains node_allocator_base from //!node_allocator_base template<class T2> struct rebind - { + { typedef node_allocator_base<Version, T2, SegmentManager, NodesPerBlock> other; }; @@ -121,15 +121,15 @@ class node_allocator_base //!Constructor from a segment manager. If not present, constructs a node //!pool. Increments the reference count of the associated node pool. //!Can throw boost::interprocess::bad_alloc - node_allocator_base(segment_manager *segment_mngr) + node_allocator_base(segment_manager *segment_mngr) : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::type>(segment_mngr)) { } - //!Copy constructor from other node_allocator_base. Increments the reference + //!Copy constructor from other node_allocator_base. Increments the reference //!count of the associated node pool. Never throws - node_allocator_base(const node_allocator_base &other) - : mp_node_pool(other.get_node_pool()) - { - node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); + node_allocator_base(const node_allocator_base &other) + : mp_node_pool(other.get_node_pool()) + { + node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); } //!Copy constructor from related node_allocator_base. If not present, constructs @@ -150,7 +150,7 @@ class node_allocator_base //!Destructor, removes node_pool_t from memory //!if its reference count reaches to zero. Never throws - ~node_allocator_base() + ~node_allocator_base() { ipcdetail::destroy_node_pool_if_last_link(node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))); } //!Returns a pointer to the node pool. @@ -177,14 +177,14 @@ class node_allocator_base //!Equality test for same type //!of node_allocator_base template<unsigned int V, class T, class S, std::size_t NPC> inline -bool operator==(const node_allocator_base<V, T, S, NPC> &alloc1, +bool operator==(const node_allocator_base<V, T, S, NPC> &alloc1, const node_allocator_base<V, T, S, NPC> &alloc2) { return alloc1.get_node_pool() == alloc2.get_node_pool(); } //!Inequality test for same type //!of node_allocator_base template<unsigned int V, class T, class S, std::size_t NPC> inline -bool operator!=(const node_allocator_base<V, T, S, NPC> &alloc1, +bool operator!=(const node_allocator_base<V, T, S, NPC> &alloc1, const node_allocator_base<V, T, S, NPC> &alloc2) { return alloc1.get_node_pool() != alloc2.get_node_pool(); } @@ -206,11 +206,11 @@ class node_allocator_v1 template<class T2> struct rebind - { + { typedef node_allocator_v1<T2, SegmentManager, NodesPerBlock> other; }; - node_allocator_v1(SegmentManager *segment_mngr) + node_allocator_v1(SegmentManager *segment_mngr) : base_t(segment_mngr) {} @@ -225,12 +225,12 @@ class node_allocator_v1 /// @endcond -//!An STL node allocator that uses a segment manager as memory +//!An STL node allocator that uses a segment manager as memory //!source. The internal pointer type will of the same type (raw, smart) as //!"typename SegmentManager::void_pointer" type. This allows //!placing the allocator in shared memory, memory mapped-files, etc... -//!This node allocator shares a segregated storage between all instances -//!of node_allocator with equal sizeof(T) placed in the same segment +//!This node allocator shares a segregated storage between all instances +//!of node_allocator with equal sizeof(T) placed in the same segment //!group. NodesPerBlock is the number of nodes allocated at once when the allocator //!needs runs out of nodes template < class T @@ -256,11 +256,11 @@ class node_allocator template<class T2> struct rebind - { + { typedef node_allocator<T2, SegmentManager, NodesPerBlock> other; }; - node_allocator(SegmentManager *segment_mngr) + node_allocator(SegmentManager *segment_mngr) : base_t(segment_mngr) {} @@ -284,11 +284,11 @@ class node_allocator typedef typename segment_manager::size_type size_type; typedef typename segment_manager::difference_type difference_type; - //!Obtains node_allocator from + //!Obtains node_allocator from //!node_allocator template<class T2> struct rebind - { + { typedef node_allocator<T2, SegmentManager, NodesPerBlock> other; }; @@ -299,7 +299,7 @@ class node_allocator node_allocator& operator= (const node_allocator<T2, SegmentManager2, N2>&); - //!Not assignable from + //!Not assignable from //!other node_allocator //node_allocator& operator=(const node_allocator&); @@ -309,7 +309,7 @@ class node_allocator //!Can throw boost::interprocess::bad_alloc node_allocator(segment_manager *segment_mngr); - //!Copy constructor from other node_allocator. Increments the reference + //!Copy constructor from other node_allocator. Increments the reference //!count of the associated node pool. Never throws node_allocator(const node_allocator &other); @@ -336,7 +336,7 @@ class node_allocator //!Never throws size_type max_size() const; - //!Allocate memory for an array of count elements. + //!Allocate memory for an array of count elements. //!Throws boost::interprocess::bad_alloc if there is no enough memory pointer allocate(size_type count, cvoid_pointer hint = 0); @@ -360,7 +360,7 @@ class node_allocator //!Never throws const_pointer address(const_reference value) const; - //!Copy construct an object. + //!Copy construct an object. //!Throws if T's copy constructor throws void construct(const pointer &ptr, const_reference v); @@ -375,7 +375,7 @@ class node_allocator std::pair<pointer, bool> allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, + size_type limit_size, size_type preferred_size, size_type &received_size, const pointer &reuse = 0); @@ -433,13 +433,13 @@ class node_allocator //!Equality test for same type //!of node_allocator template<class T, class S, std::size_t NPC> inline -bool operator==(const node_allocator<T, S, NPC> &alloc1, +bool operator==(const node_allocator<T, S, NPC> &alloc1, const node_allocator<T, S, NPC> &alloc2); //!Inequality test for same type //!of node_allocator template<class T, class S, std::size_t NPC> inline -bool operator!=(const node_allocator<T, S, NPC> &alloc1, +bool operator!=(const node_allocator<T, S, NPC> &alloc1, const node_allocator<T, S, NPC> &alloc2); #endif diff --git a/boost/interprocess/allocators/private_adaptive_pool.hpp b/boost/interprocess/allocators/private_adaptive_pool.hpp index 301fb92daa..febe85c69d 100644 --- a/boost/interprocess/allocators/private_adaptive_pool.hpp +++ b/boost/interprocess/allocators/private_adaptive_pool.hpp @@ -33,7 +33,7 @@ #include <cstddef> //!\file -//!Describes private_adaptive_pool_base pooled shared memory STL compatible allocator +//!Describes private_adaptive_pool_base pooled shared memory STL compatible allocator namespace boost { namespace interprocess { @@ -102,7 +102,7 @@ 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; }; @@ -154,7 +154,7 @@ class private_adaptive_pool_base {} //!Destructor, frees all used memory. Never throws - ~private_adaptive_pool_base() + ~private_adaptive_pool_base() {} //!Returns the segment manager. Never throws @@ -178,13 +178,13 @@ class private_adaptive_pool_base //!Equality test for same type of private_adaptive_pool_base template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline -bool operator==(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1, +bool operator==(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1, const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc2) { return &alloc1 == &alloc2; } //!Inequality test for same type of private_adaptive_pool_base template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline -bool operator!=(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1, +bool operator!=(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1, const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc2) { return &alloc1 != &alloc2; } @@ -210,11 +210,11 @@ class private_adaptive_pool_v1 template<class T2> struct rebind - { + { typedef private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; - private_adaptive_pool_v1(SegmentManager *segment_mngr) + private_adaptive_pool_v1(SegmentManager *segment_mngr) : base_t(segment_mngr) {} @@ -229,7 +229,7 @@ class private_adaptive_pool_v1 /// @endcond -//!An STL node allocator that uses a segment manager as memory +//!An STL node allocator that uses a segment manager as memory //!source. The internal pointer type will of the same type (raw, smart) as //!"typename SegmentManager::void_pointer" type. This allows //!placing the allocator in shared memory, memory mapped-files, etc... @@ -269,12 +269,12 @@ class private_adaptive_pool template<class T2> struct rebind - { + { typedef private_adaptive_pool <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; - private_adaptive_pool(SegmentManager *segment_mngr) + private_adaptive_pool(SegmentManager *segment_mngr) : base_t(segment_mngr) {} @@ -298,11 +298,11 @@ class private_adaptive_pool typedef typename segment_manager::size_type size_type; typedef typename segment_manager::difference_type difference_type; - //!Obtains private_adaptive_pool from + //!Obtains private_adaptive_pool from //!private_adaptive_pool template<class T2> struct rebind - { + { typedef private_adaptive_pool <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -314,7 +314,7 @@ class private_adaptive_pool private_adaptive_pool& operator= (const private_adaptive_pool<T2, SegmentManager2, N2, F2>&); - //!Not assignable from + //!Not assignable from //!other private_adaptive_pool private_adaptive_pool& operator=(const private_adaptive_pool&); @@ -324,7 +324,7 @@ class private_adaptive_pool //!Can throw boost::interprocess::bad_alloc private_adaptive_pool(segment_manager *segment_mngr); - //!Copy constructor from other private_adaptive_pool. Increments the reference + //!Copy constructor from other private_adaptive_pool. Increments the reference //!count of the associated node pool. Never throws private_adaptive_pool(const private_adaptive_pool &other); @@ -351,7 +351,7 @@ class private_adaptive_pool //!Never throws size_type max_size() const; - //!Allocate memory for an array of count elements. + //!Allocate memory for an array of count elements. //!Throws boost::interprocess::bad_alloc if there is no enough memory pointer allocate(size_type count, cvoid_pointer hint = 0); @@ -375,7 +375,7 @@ class private_adaptive_pool //!Never throws const_pointer address(const_reference value) const; - //!Copy construct an object. + //!Copy construct an object. //!Throws if T's copy constructor throws void construct(const pointer &ptr, const_reference v); @@ -390,7 +390,7 @@ class private_adaptive_pool std::pair<pointer, bool> allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, + size_type limit_size, size_type preferred_size, size_type &received_size, const pointer &reuse = 0); @@ -448,13 +448,13 @@ class private_adaptive_pool //!Equality test for same type //!of private_adaptive_pool template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline -bool operator==(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, +bool operator==(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2); //!Inequality test for same type //!of private_adaptive_pool template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline -bool operator!=(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, +bool operator!=(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2); #endif diff --git a/boost/interprocess/allocators/private_node_allocator.hpp b/boost/interprocess/allocators/private_node_allocator.hpp index f202e316fa..46b7dd6097 100644 --- a/boost/interprocess/allocators/private_node_allocator.hpp +++ b/boost/interprocess/allocators/private_node_allocator.hpp @@ -33,7 +33,7 @@ #include <cstddef> //!\file -//!Describes private_node_allocator_base pooled shared memory STL compatible allocator +//!Describes private_node_allocator_base pooled shared memory STL compatible allocator namespace boost { namespace interprocess { @@ -97,7 +97,7 @@ 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; }; @@ -146,7 +146,7 @@ class private_node_allocator_base {} //!Destructor, frees all used memory. Never throws - ~private_node_allocator_base() + ~private_node_allocator_base() {} //!Returns the segment manager. Never throws @@ -170,13 +170,13 @@ class private_node_allocator_base //!Equality test for same type of private_node_allocator_base template<unsigned int V, class T, class S, std::size_t NPC> inline -bool operator==(const private_node_allocator_base<V, T, S, NPC> &alloc1, +bool operator==(const private_node_allocator_base<V, T, S, NPC> &alloc1, const private_node_allocator_base<V, T, S, NPC> &alloc2) { return &alloc1 == &alloc2; } //!Inequality test for same type of private_node_allocator_base template<unsigned int V, class T, class S, std::size_t NPC> inline -bool operator!=(const private_node_allocator_base<V, T, S, NPC> &alloc1, +bool operator!=(const private_node_allocator_base<V, T, S, NPC> &alloc1, const private_node_allocator_base<V, T, S, NPC> &alloc2) { return &alloc1 != &alloc2; } @@ -198,11 +198,11 @@ class private_node_allocator_v1 template<class T2> struct rebind - { + { typedef private_node_allocator_v1<T2, SegmentManager, NodesPerBlock> other; }; - private_node_allocator_v1(SegmentManager *segment_mngr) + private_node_allocator_v1(SegmentManager *segment_mngr) : base_t(segment_mngr) {} @@ -217,11 +217,11 @@ class private_node_allocator_v1 /// @endcond -//!An STL node allocator that uses a segment manager as memory +//!An STL node allocator that uses a segment manager as memory //!source. The internal pointer type will of the same type (raw, smart) as //!"typename SegmentManager::void_pointer" type. This allows //!placing the allocator in shared memory, memory mapped-files, etc... -//!This allocator has its own node pool. NodesPerBlock is the number of nodes allocated +//!This allocator has its own node pool. NodesPerBlock is the number of nodes allocated //!at once when the allocator needs runs out of nodes template < class T , class SegmentManager @@ -246,12 +246,12 @@ class private_node_allocator template<class T2> struct rebind - { + { typedef private_node_allocator <T2, SegmentManager, NodesPerBlock> other; }; - private_node_allocator(SegmentManager *segment_mngr) + private_node_allocator(SegmentManager *segment_mngr) : base_t(segment_mngr) {} @@ -275,11 +275,11 @@ class private_node_allocator typedef typename segment_manager::size_type size_type; typedef typename segment_manage::difference_type difference_type; - //!Obtains private_node_allocator from + //!Obtains private_node_allocator from //!private_node_allocator template<class T2> struct rebind - { + { typedef private_node_allocator <T2, SegmentManager, NodesPerBlock> other; }; @@ -291,7 +291,7 @@ class private_node_allocator private_node_allocator& operator= (const private_node_allocator<T2, SegmentManager2, N2>&); - //!Not assignable from + //!Not assignable from //!other private_node_allocator private_node_allocator& operator=(const private_node_allocator&); @@ -301,7 +301,7 @@ class private_node_allocator //!Can throw boost::interprocess::bad_alloc private_node_allocator(segment_manager *segment_mngr); - //!Copy constructor from other private_node_allocator. Increments the reference + //!Copy constructor from other private_node_allocator. Increments the reference //!count of the associated node pool. Never throws private_node_allocator(const private_node_allocator &other); @@ -328,7 +328,7 @@ class private_node_allocator //!Never throws size_type max_size() const; - //!Allocate memory for an array of count elements. + //!Allocate memory for an array of count elements. //!Throws boost::interprocess::bad_alloc if there is no enough memory pointer allocate(size_type count, cvoid_pointer hint = 0); @@ -352,7 +352,7 @@ class private_node_allocator //!Never throws const_pointer address(const_reference value) const; - //!Copy construct an object. + //!Copy construct an object. //!Throws if T's copy constructor throws void construct(const pointer &ptr, const_reference v); @@ -367,7 +367,7 @@ class private_node_allocator std::pair<pointer, bool> allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, + size_type limit_size, size_type preferred_size, size_type &received_size, const pointer &reuse = 0); @@ -425,13 +425,13 @@ class private_node_allocator //!Equality test for same type //!of private_node_allocator template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline -bool operator==(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1, +bool operator==(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1, const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc2); //!Inequality test for same type //!of private_node_allocator template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline -bool operator!=(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1, +bool operator!=(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1, const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc2); #endif diff --git a/boost/interprocess/anonymous_shared_memory.hpp b/boost/interprocess/anonymous_shared_memory.hpp index 7184306a6d..624f57f9c3 100644 --- a/boost/interprocess/anonymous_shared_memory.hpp +++ b/boost/interprocess/anonymous_shared_memory.hpp @@ -20,7 +20,7 @@ #include <cstddef> #if (!defined(BOOST_INTERPROCESS_WINDOWS)) -# include <fcntl.h> //open, O_CREAT, O_*... +# include <fcntl.h> //open, O_CREAT, O_*... # include <sys/mman.h> //mmap # include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU, #else @@ -43,12 +43,10 @@ namespace ipcdetail{ { public: static mapped_region - create_posix_mapped_region(void *address, offset_t offset, std::size_t size) + create_posix_mapped_region(void *address, std::size_t size) { mapped_region region; region.m_base = address; - region.m_offset = offset; - region.m_extra_offset = 0; region.m_size = size; return region; } @@ -92,16 +90,16 @@ 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, 0, size); + return ipcdetail::raw_mapped_region_creator::create_posix_mapped_region(address, size); } #else { diff --git a/boost/interprocess/detail/atomic.hpp b/boost/interprocess/detail/atomic.hpp index f7551f3dda..aab1533985 100644 --- a/boost/interprocess/detail/atomic.hpp +++ b/boost/interprocess/detail/atomic.hpp @@ -117,23 +117,6 @@ inline boost::uint32_t atomic_cas32 : "cc"); return prev; -/* - asm volatile( "lock\n\t" - "cmpxchg %3,%1" - : "=a" (prev), "=m" (*(mem)) - : "0" (prev), "r" (with) - : "memory", "cc"); -*/ -/* - boost::uint32_t prev; - - asm volatile ("lock; cmpxchgl %1, %2" - : "=a" (prev) - : "r" (with), "m" (*(mem)), "0"(cmp)); - asm volatile("" : : : "memory"); - - return prev; -*/ } //! Atomically add 'val' to an boost::uint32_t @@ -158,14 +141,6 @@ inline boost::uint32_t atomic_add32 ); return r; -/* - asm volatile( "lock\n\t; xaddl %0,%1" - : "=r"(val), "=m"(*mem) - : "0"(val), "m"(*mem)); - asm volatile("" : : : "memory"); - - return val; -*/ } //! Atomically increment an apr_uint32_t by 1 @@ -208,17 +183,14 @@ inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32 { boost::uint32_t prev, temp; - asm volatile ("0:\n\t" // retry local label - "lwarx %0,0,%2\n\t" // load prev and reserve - "add %1,%0,%3\n\t" // temp = prev + val - "stwcx. %1,0,%2\n\t" // conditionally store - "bne- 0b" // start over if we lost - // the reservation - //XXX find a cleaner way to define the temp - //it's not an output - : "=&r" (prev), "=&r" (temp) // output, temp - : "b" (mem), "r" (val) // inputs - : "memory", "cc"); // clobbered + asm volatile ("1:\n\t" + "lwarx %0,0,%2\n\t" + "add %1,%0,%3\n\t" + "stwcx. %1,0,%2\n\t" + "bne- 1b" + : "=&r" (prev), "=&r" (temp) + : "b" (mem), "r" (val) + : "cc", "memory"); return prev; } @@ -233,19 +205,16 @@ inline boost::uint32_t atomic_cas32 { boost::uint32_t prev; - asm volatile ("0:\n\t" // retry local label - "lwarx %0,0,%1\n\t" // load prev and reserve - "cmpw %0,%3\n\t" // does it match cmp? - "bne- 1f\n\t" // ...no, bail out - "stwcx. %2,0,%1\n\t" // ...yes, conditionally - // store with - "bne- 0b\n\t" // start over if we lost - // the reservation - "1:" // exit local label - - : "=&r"(prev) // output - : "b" (mem), "r" (with), "r"(cmp) // inputs - : "memory", "cc"); // clobbered + asm volatile ("1:\n\t" + "lwarx %0,0,%1\n\t" + "cmpw %0,%3\n\t" + "bne- 2f\n\t" + "stwcx. %2,0,%1\n\t" + "bne- 1b\n\t" + "2:" + : "=&r"(prev) + : "b" (mem), "r"(cmp), "r" (with) + : "cc", "memory"); return prev; } @@ -275,56 +244,6 @@ inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) } //namespace interprocess{ } //namespace boost{ -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) - -namespace boost { -namespace interprocess { -namespace ipcdetail{ - -//! Atomically add 'val' to an boost::uint32_t -//! "mem": pointer to the object -//! "val": amount to add -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_add32 - (volatile boost::uint32_t *mem, boost::uint32_t val) -{ return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val); } - -//! Atomically increment an apr_uint32_t by 1 -//! "mem": pointer to the object -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) -{ return atomic_add32(mem, 1); } - -//! Atomically decrement an boost::uint32_t by 1 -//! "mem": pointer to the atomic value -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) -{ return atomic_add32(mem, (boost::uint32_t)-1); } - -//! Atomically read an boost::uint32_t from memory -inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } - -//! Compare an boost::uint32_t's value with "cmp". -//! If they are the same swap the value with "with" -//! "mem": pointer to the value -//! "with" what to swap it with -//! "cmp": the value to compare it to -//! Returns the old value of *mem -inline boost::uint32_t atomic_cas32 - (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) -{ return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with); } - -//! Atomically set an boost::uint32_t in memory -//! "mem": pointer to the object -//! "param": val value that the object will assume -inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) -{ *mem = val; } - -} //namespace ipcdetail{ -} //namespace interprocess{ -} //namespace boost{ - #elif (defined(sun) || defined(__sun)) #include <atomic.h> @@ -471,97 +390,147 @@ 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 -} //namespace boost +#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX) + +#include <builtins.h> + +namespace boost { +namespace interprocess { +namespace ipcdetail{ + +//first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting +//all the functions with casts + +//! From XLC documenation : +//! This function can be used with a subsequent stwcxu call to implement a +//! read-modify-write on a specified memory location. The two functions work +//! together to ensure that if the store is successfully performed, no other +//! processor or mechanism can modify the target doubleword between the time +//! lwarxu function is executed and the time the stwcxu functio ncompletes. +//! "mem" : pointer to the object +//! Returns the value at pointed to by mem +inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem) +{ + return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem))); +} + +//! "mem" : pointer to the object +//! "val" : the value to store +//! Returns true if the update of mem is successful and false if it is +//!unsuccessful +inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val) +{ + return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0); +} + +//! "mem": pointer to the object +//! "val": amount to add +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_add32 + (volatile boost::uint32_t *mem, boost::uint32_t val) +{ + boost::uint32_t oldValue; + do + { + oldValue = lwarxu(mem); + }while (!stwcxu(mem, oldValue+val)); + return oldValue; +} + +//! Atomically increment an apr_uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, 1); } + +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, (boost::uint32_t)-1); } + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } + +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with" what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +inline boost::uint32_t atomic_cas32 + (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) +{ + boost::uint32_t oldValue; + boost::uint32_t valueToStore; + do + { + oldValue = lwarxu(mem); + } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue)); + + return oldValue; +} + +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ *mem = val; } + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +namespace boost { +namespace interprocess { +namespace ipcdetail{ + +//! Atomically add 'val' to an boost::uint32_t +//! "mem": pointer to the object +//! "val": amount to add +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_add32 + (volatile boost::uint32_t *mem, boost::uint32_t val) +{ return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val); } + +//! Atomically increment an apr_uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, 1); } + +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, (boost::uint32_t)-1); } + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } + +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with" what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +inline boost::uint32_t atomic_cas32 + (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) +{ return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with); } + +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ *mem = val; } + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ #else @@ -583,9 +552,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/config_begin.hpp b/boost/interprocess/detail/config_begin.hpp index 559331ab32..a72f6df1fe 100644 --- a/boost/interprocess/detail/config_begin.hpp +++ b/boost/interprocess/detail/config_begin.hpp @@ -44,4 +44,5 @@ // with /GR-; unpredictable behavior may result #pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site #pragma warning (disable : 4671) // the copy constructor is inaccessible + #pragma warning (disable : 4250) // inherits 'x' via dominance #endif diff --git a/boost/interprocess/detail/file_locking_helpers.hpp b/boost/interprocess/detail/file_locking_helpers.hpp new file mode 100644 index 0000000000..2b96e2b6d5 --- /dev/null +++ b/boost/interprocess/detail/file_locking_helpers.hpp @@ -0,0 +1,298 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP +#define BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP + +#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> + +#include <sstream> +#include <string> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <cstddef> +#include <boost/interprocess/detail/os_file_functions.hpp> + +#include <boost/interprocess/detail/tmp_dir_helpers.hpp> + +#if defined(BOOST_INTERPROCESS_WINDOWS) + +#include <fcntl.h> +#include <io.h> +#include <sys/locking.h> + +#else //defined(BOOST_INTERPROCESS_WINDOWS) + +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> + +#endif //defined(BOOST_INTERPROCESS_WINDOWS) + +namespace boost{ +namespace interprocess{ +namespace ipcdetail{ + +#if defined(BOOST_INTERPROCESS_WINDOWS) + +struct locking_file_serial_id +{ + int fd; + unsigned long dwVolumeSerialNumber; + unsigned long nFileIndexHigh; + unsigned long nFileIndexLow; + //This reference count counts the number of modules attached + //to the shared memory and lock file. This serves to unlink + //the locking file and shared memory when all modules are + //done with the global memory (shared memory) + volatile boost::uint32_t modules_attached_to_gmem_count; +}; + +inline bool lock_locking_file(int fd) +{ + int ret = 0; + while(ret != 0 && errno == EDEADLK){ + ret = _locking(fd, _LK_LOCK, 1/*lock_file_contents_length()*/); + } + return 0 == ret; +} + +inline bool try_lock_locking_file(int fd) +{ + return 0 == _locking(fd, _LK_NBLCK , 1); +} + +inline int open_or_create_and_lock_file(const char *name) +{ + permissions p; + p.set_unrestricted(); + while(1){ + file_handle_t handle = create_or_open_file(name, read_write, p); + int fd = _open_osfhandle((intptr_t)handle, _O_TEXT); + if(fd < 0){ + close_file(handle); + return fd; + } + if(!try_lock_locking_file(fd)){ + _close(fd); + return -1; + } + struct _stat s; + if(0 == _stat(name, &s)){ + return fd; + } + else{ + _close(fd); + } + } +} + +inline int try_open_and_lock_file(const char *name) +{ + file_handle_t handle = open_existing_file(name, read_write); + int fd = _open_osfhandle((intptr_t)handle, _O_TEXT); + if(fd < 0){ + close_file(handle); + return fd; + } + if(!try_lock_locking_file(fd)){ + _close(fd); + return -1; + } + return fd; +} + +inline void close_lock_file(int fd) +{ _close(fd); } + +inline bool is_valid_fd(int fd) +{ + struct _stat s; + return EBADF != _fstat(fd, &s); +} + +inline bool is_normal_file(int fd) +{ + if(_isatty(fd)) + return false; + struct _stat s; + if(0 != _fstat(fd, &s)) + return false; + return 0 != (s.st_mode & _S_IFREG); +} + +inline std::size_t get_size(int fd) +{ + struct _stat s; + if(0 != _fstat(fd, &s)) + return 0u; + return (std::size_t)s.st_size; +} + +inline bool fill_file_serial_id(int fd, locking_file_serial_id &id) +{ + winapi::interprocess_by_handle_file_information info; + if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info)) + return false; + id.fd = fd; + id.dwVolumeSerialNumber = info.dwVolumeSerialNumber; + id.nFileIndexHigh = info.nFileIndexHigh; + id.nFileIndexLow = info.nFileIndexLow; + id.modules_attached_to_gmem_count = 1; //Initialize attached count + return true; +} + +inline bool compare_file_serial(int fd, const locking_file_serial_id &id) +{ + winapi::interprocess_by_handle_file_information info; + if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info)) + return false; + + return id.dwVolumeSerialNumber == info.dwVolumeSerialNumber && + id.nFileIndexHigh == info.nFileIndexHigh && + id.nFileIndexLow == info.nFileIndexLow; +} + +#else //UNIX + +struct locking_file_serial_id +{ + int fd; + dev_t st_dev; + ino_t st_ino; + //This reference count counts the number of modules attached + //to the shared memory and lock file. This serves to unlink + //the locking file and shared memory when all modules are + //done with the global memory (shared memory) + volatile boost::uint32_t modules_attached_to_gmem_count; +}; + +inline bool lock_locking_file(int fd) +{ + int ret = 0; + while(ret != 0 && errno != EINTR){ + struct flock lock; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 1; + ret = fcntl (fd, F_SETLKW, &lock); + } + return 0 == ret; +} + +inline bool try_lock_locking_file(int fd) +{ + struct flock lock; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 1; + return 0 == fcntl (fd, F_SETLK, &lock); +} + +inline int open_or_create_and_lock_file(const char *name) +{ + permissions p; + p.set_unrestricted(); + while(1){ + int fd = create_or_open_file(name, read_write, p); + if(fd < 0){ + return fd; + } + if(!try_lock_locking_file(fd)){ + close(fd); + return -1; + } + struct stat s; + if(0 == stat(name, &s)){ + return fd; + } + else{ + close(fd); + } + } +} + +inline int try_open_and_lock_file(const char *name) +{ + int fd = open_existing_file(name, read_write); + if(fd < 0){ + return fd; + } + if(!try_lock_locking_file(fd)){ + close(fd); + return -1; + } + return fd; +} + +inline void close_lock_file(int fd) +{ close(fd); } + +inline bool is_valid_fd(int fd) +{ + struct stat s; + return EBADF != fstat(fd, &s); +} + +inline bool is_normal_file(int fd) +{ + struct stat s; + if(0 != fstat(fd, &s)) + return false; + return 0 != (s.st_mode & S_IFREG); +} + +inline std::size_t get_size(int fd) +{ + struct stat s; + if(0 != fstat(fd, &s)) + return 0u; + return (std::size_t)s.st_size; +} + +inline bool fill_file_serial_id(int fd, locking_file_serial_id &id) +{ + struct stat s; + if(0 != fstat(fd, &s)) + return false; + id.fd = fd; + id.st_dev = s.st_dev; + id.st_ino = s.st_ino; + id.modules_attached_to_gmem_count = 1; //Initialize attached count + return true; +} + +inline bool compare_file_serial(int fd, const locking_file_serial_id &id) +{ + struct stat info; + if(0 != fstat(fd, &info)) + return false; + + return id.st_dev == info.st_dev && + id.st_ino == info.st_ino; +} + +#endif + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP diff --git a/boost/interprocess/detail/file_wrapper.hpp b/boost/interprocess/detail/file_wrapper.hpp index 7b53f36ac8..586e20db4d 100644 --- a/boost/interprocess/detail/file_wrapper.hpp +++ b/boost/interprocess/detail/file_wrapper.hpp @@ -44,13 +44,13 @@ class file_wrapper file_wrapper(open_or_create_t, const char *name, mode_t mode, const permissions &perm = permissions()) { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm); } - //!Tries to open a file with name "name", with the access mode "mode". + //!Tries to open a file with name "name", with the access mode "mode". //!If the file does not previously exist, it throws an error. file_wrapper(open_only_t, const char *name, mode_t mode) { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); } - //!Moves the ownership of "moved"'s file to *this. - //!After the call, "moved" does not represent any file. + //!Moves the ownership of "moved"'s file to *this. + //!After the call, "moved" does not represent any file. //!Does not throw file_wrapper(BOOST_RV_REF(file_wrapper) moved) : m_handle(file_handle_t(ipcdetail::invalid_file())) @@ -60,10 +60,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 +73,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); @@ -108,11 +108,11 @@ class file_wrapper std::string m_filename; }; -inline file_wrapper::file_wrapper() +inline file_wrapper::file_wrapper() : m_handle(file_handle_t(ipcdetail::invalid_file())) {} -inline file_wrapper::~file_wrapper() +inline file_wrapper::~file_wrapper() { this->priv_close(); } inline const char *file_wrapper::get_name() const @@ -122,10 +122,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 @@ -135,7 +135,7 @@ inline mode_t file_wrapper::get_mode() const { return m_mode; } inline bool file_wrapper::priv_open_or_create - (ipcdetail::create_enum_t type, + (ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm = permissions()) diff --git a/boost/interprocess/detail/in_place_interface.hpp b/boost/interprocess/detail/in_place_interface.hpp index 0e69452a40..b43b2ce165 100644 --- a/boost/interprocess/detail/in_place_interface.hpp +++ b/boost/interprocess/detail/in_place_interface.hpp @@ -25,7 +25,7 @@ //!Describes an abstract interface for placement construction and destruction. namespace boost { -namespace interprocess { +namespace interprocess { namespace ipcdetail { struct in_place_interface diff --git a/boost/interprocess/detail/intermodule_singleton.hpp b/boost/interprocess/detail/intermodule_singleton.hpp index 4bffbe9d4e..054322699d 100644 --- a/boost/interprocess/detail/intermodule_singleton.hpp +++ b/boost/interprocess/detail/intermodule_singleton.hpp @@ -18,1163 +18,27 @@ #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> -#if defined(BOOST_INTERPROCESS_WINDOWS) -#include <boost/interprocess/windows_shared_memory.hpp> -#endif - -#include <boost/interprocess/shared_memory_object.hpp> - -#include <boost/interprocess/offset_ptr.hpp> -#include <boost/interprocess/sync/spin/mutex.hpp> -#include <boost/interprocess/sync/spin/recursive_mutex.hpp> -#include <boost/interprocess/detail/managed_memory_impl.hpp> -#include <boost/interprocess/detail/managed_open_or_create_impl.hpp> -#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> -#include <boost/interprocess/indexes/iset_index.hpp> -#include <boost/interprocess/creation_tags.hpp> -#include <boost/interprocess/permissions.hpp> - - -#include <boost/interprocess/detail/atomic.hpp> -#include <boost/interprocess/detail/os_thread_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> -#include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/interprocess/detail/mpl.hpp> -#include <boost/type_traits/type_with_alignment.hpp> -#include <boost/assert.hpp> -#include <cstddef> -#include <cstdio> -#include <cstring> -#include <string> - -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> - -#if defined(BOOST_INTERPROCESS_WINDOWS) -#include <fcntl.h> -#include <io.h> - -#include <sys/locking.h> -#else -#include <fcntl.h> -#include <sys/stat.h> -#include <unistd.h> +#ifdef BOOST_INTERPROCESS_WINDOWS + #include <boost/interprocess/detail/windows_intermodule_singleton.hpp> #endif +#include <boost/interprocess/detail/portable_intermodule_singleton.hpp> namespace boost{ namespace interprocess{ namespace ipcdetail{ -struct intermodule_singleton_mutex_family -{ - typedef boost::interprocess::ipcdetail::spin_mutex mutex_type; - typedef boost::interprocess::ipcdetail::spin_recursive_mutex recursive_mutex_type; -}; - -struct intermodule_types -{ - //We must use offset_ptr since a loaded DLL can map the singleton holder shared memory - //at a different address than other DLLs/main executables - typedef rbtree_best_fit<intermodule_singleton_mutex_family, offset_ptr<void> > mem_algo; - template<class Device, bool FileBased> - struct open_or_create - { - typedef managed_open_or_create_impl - <Device, mem_algo::Alignment, FileBased> type; - }; -}; - -template<class Device, bool FileBased> -class basic_managed_global_memory - : public basic_managed_memory_impl - < char - , intermodule_types::mem_algo - , iset_index - , intermodule_types::open_or_create<Device, FileBased>::type::ManagedOpenOrCreateUserOffset - > - , private intermodule_types::open_or_create<Device, FileBased>::type -{ - /// @cond - typedef typename intermodule_types::template open_or_create<Device, FileBased>::type base2_t; - - typedef basic_managed_memory_impl - < char - , intermodule_types::mem_algo - , iset_index - , base2_t::ManagedOpenOrCreateUserOffset - > base_t; - - typedef create_open_func<base_t> create_open_func_t; - - basic_managed_global_memory *get_this_pointer() - { return this; } - - public: - typedef typename base_t::size_type size_type; - - private: - typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; - BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_global_memory) - /// @endcond - - public: //functions -/* - basic_managed_global_memory() - {} - - basic_managed_global_memory(create_only_t create_only, const char *name, - size_type size, const void *addr = 0, const permissions& perm = permissions()) - : base_t() - , base2_t(create_only, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), DoCreate), perm) - {} -*/ - basic_managed_global_memory (open_or_create_t open_or_create, - const char *name, size_type size, - const void *addr = 0, const permissions& perm = permissions()) - : base_t() - , base2_t(open_or_create, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), - DoOpenOrCreate), perm) - {} - - basic_managed_global_memory (open_only_t open_only, const char* name, - const void *addr = 0) - : base_t() - , base2_t(open_only, name, read_write, addr, - create_open_func_t(get_this_pointer(), - DoOpen)) - {} - -/* - basic_managed_global_memory (open_copy_on_write_t, const char* name, - const void *addr = 0) - : base_t() - , base2_t(open_only, name, copy_on_write, addr, - create_open_func_t(get_this_pointer(), - DoOpen)) - {} - - //!Connects to a created shared memory and its segment manager. - //!in read-only mode. - //!This can throw. - basic_managed_global_memory (open_read_only_t, const char* name, - const void *addr = 0) - : base_t() - , base2_t(open_only, name, read_only, addr, - create_open_func_t(get_this_pointer(), - DoOpen)) - {} - - //!Moves the ownership of "moved"'s managed memory to *this. - //!Does not throw - basic_managed_global_memory(BOOST_RV_REF(basic_managed_global_memory) moved) - { - basic_managed_global_memory tmp; - this->swap(moved); - tmp.swap(moved); - } - - //!Moves the ownership of "moved"'s managed memory to *this. - //!Does not throw - basic_managed_global_memory &operator=(BOOST_RV_REF(basic_managed_global_memory) moved) - { - basic_managed_global_memory tmp(boost::move(moved)); - this->swap(tmp); - return *this; - }*/ -}; - -#if defined(BOOST_INTERPROCESS_WINDOWS) -typedef basic_managed_global_memory<windows_shared_memory, false> windows_managed_global_memory; -#endif - -typedef basic_managed_global_memory<shared_memory_object, true> managed_global_memory; - -namespace file_locking_helpers { - -inline void get_pid_creation_time_str(std::string &s) -{ - std::stringstream stream; - stream << get_current_process_id() << '_'; - stream.precision(6); - stream << std::fixed << get_current_process_creation_time(); - s = stream.str(); -} - -inline void create_tmp_subdir_and_get_pid_based_filepath(const char *subdir_name, const char *file_prefix, OS_process_id_t pid, std::string &s, bool creation_time = false) -{ - //Let's create a lock file for each process gmem that will mark if - //the process is alive or not - create_tmp_and_clean_old(s); - s += "/"; - s += subdir_name; - if(!open_or_create_directory(s.c_str())){ - throw interprocess_exception(error_info(system_error_code())); - } - s += "/"; - s += file_prefix; - if(creation_time){ - std::string sstamp; - get_pid_creation_time_str(sstamp); - s += sstamp; - } - else{ - pid_str_t pid_str; - get_pid_str(pid_str, pid); - s += pid_str; - } -} - -inline bool check_if_filename_complies_with_pid - (const char *filename, const char *prefix, OS_process_id_t pid, std::string &file_suffix, bool creation_time = false) -{ - //Check if filename complies with lock file name pattern - std::string fname(filename); - std::string fprefix(prefix); - if(fname.size() <= fprefix.size()){ - return false; - } - fname.resize(fprefix.size()); - if(fname != fprefix){ - return false; - } - - //If not our lock file, delete it if we can lock it - fname = filename; - fname.erase(0, fprefix.size()); - pid_str_t pid_str; - get_pid_str(pid_str, pid); - file_suffix = pid_str; - if(creation_time){ - std::size_t p = fname.find('_'); - if (p == std::string::npos){ - return false; - } - std::string save_suffix(fname); - fname.erase(p); - fname.swap(file_suffix); - bool ret = (file_suffix == fname); - file_suffix.swap(save_suffix); - return ret; - } - else{ - fname.swap(file_suffix); - return (file_suffix == fname); - } -} - -} //file_locking_helpers - -namespace intermodule_singleton_helpers { - -const int GMemMarkToBeRemoved = -1; -const int GMemNotPresent = -2; - -inline const char *get_lock_file_subdir_name() -{ return "gmem"; } - -inline const char *get_lock_file_base_name() -{ return "lck"; } - -inline void create_and_get_singleton_lock_file_path(std::string &s) -{ - file_locking_helpers::create_tmp_subdir_and_get_pid_based_filepath - (get_lock_file_subdir_name(), get_lock_file_base_name(), get_current_process_id(), s, true); -} - -inline const char *get_shm_base_name() -{ return "bip.gmem.shm."; } - -inline void get_shm_name(std::string &shm_name) -{ - file_locking_helpers::get_pid_creation_time_str(shm_name); - shm_name.insert(0, get_shm_base_name()); -} - -inline std::size_t get_shm_size() -{ return 65536; } - -template<class ManagedShMem> -struct managed_sh_dependant -{ - static void apply_gmem_erase_logic(const char *filepath, const char *filename); - - static bool remove_old_gmem() - { - std::string refcstrRootDirectory; - tmp_folder(refcstrRootDirectory); - refcstrRootDirectory += "/"; - refcstrRootDirectory += get_lock_file_subdir_name(); - return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic); - } -}; - -#if defined(BOOST_INTERPROCESS_WINDOWS) - -template<> -struct managed_sh_dependant<windows_managed_global_memory> -{ - static void apply_gmem_erase_logic(const char *, const char *){} - - static bool remove_old_gmem() - { return true; } -}; - - -struct locking_file_serial_id -{ - int fd; - unsigned long dwVolumeSerialNumber; - unsigned long nFileIndexHigh; - unsigned long nFileIndexLow; - //This reference count counts the number of modules attached - //to the shared memory and lock file. This serves to unlink - //the locking file and shared memory when all modules are - //done with the global memory (shared memory) - volatile boost::uint32_t modules_attached_to_gmem_count; -}; - -inline bool lock_locking_file(int fd) -{ - int ret = 0; - while(ret != 0 && errno == EDEADLK){ - ret = _locking(fd, _LK_LOCK, 1/*lock_file_contents_length()*/); - } - return 0 == ret; -} - -inline bool try_lock_locking_file(int fd) -{ - return 0 == _locking(fd, _LK_NBLCK , 1); -} - -inline int open_or_create_and_lock_file(const char *name) -{ - permissions p; - p.set_unrestricted(); - while(1){ - file_handle_t handle = create_or_open_file(name, read_write, p); - int fd = _open_osfhandle((intptr_t)handle, _O_TEXT); - if(fd < 0){ - close_file(handle); - return fd; - } - if(!try_lock_locking_file(fd)){ - _close(fd); - return -1; - } - struct _stat s; - if(0 == _stat(name, &s)){ - return fd; - } - else{ - _close(fd); - } - } -} - -inline int try_open_and_lock_file(const char *name) -{ - file_handle_t handle = open_existing_file(name, read_write); - int fd = _open_osfhandle((intptr_t)handle, _O_TEXT); - if(fd < 0){ - close_file(handle); - return fd; - } - if(!try_lock_locking_file(fd)){ - _close(fd); - return -1; - } - return fd; -} - -inline void close_lock_file(int fd) -{ _close(fd); } - -inline bool is_valid_fd(int fd) -{ - struct _stat s; - return EBADF != _fstat(fd, &s); -} - -inline bool is_normal_file(int fd) -{ - if(_isatty(fd)) - return false; - struct _stat s; - if(0 != _fstat(fd, &s)) - return false; - return 0 != (s.st_mode & _S_IFREG); -} - -inline std::size_t get_size(int fd) -{ - struct _stat s; - if(0 != _fstat(fd, &s)) - return 0u; - return (std::size_t)s.st_size; -} - -inline bool fill_file_serial_id(int fd, locking_file_serial_id &id) -{ - winapi::interprocess_by_handle_file_information info; - if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info)) - return false; - id.fd = fd; - id.dwVolumeSerialNumber = info.dwVolumeSerialNumber; - id.nFileIndexHigh = info.nFileIndexHigh; - id.nFileIndexLow = info.nFileIndexLow; - id.modules_attached_to_gmem_count = 1; //Initialize attached count - return true; -} - -inline bool compare_file_serial(int fd, const locking_file_serial_id &id) -{ - winapi::interprocess_by_handle_file_information info; - if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info)) - return false; - - return id.dwVolumeSerialNumber == info.dwVolumeSerialNumber && - id.nFileIndexHigh == info.nFileIndexHigh && - id.nFileIndexLow == info.nFileIndexLow; -} - -#else //UNIX - -struct locking_file_serial_id -{ - int fd; - dev_t st_dev; - ino_t st_ino; - //This reference count counts the number of modules attached - //to the shared memory and lock file. This serves to unlink - //the locking file and shared memory when all modules are - //done with the global memory (shared memory) - volatile boost::uint32_t modules_attached_to_gmem_count; -}; - -inline bool lock_locking_file(int fd) -{ - int ret = 0; - while(ret != 0 && errno != EINTR){ - struct flock lock; - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 1; - ret = fcntl (fd, F_SETLKW, &lock); - } - return 0 == ret; -} - -inline bool try_lock_locking_file(int fd) -{ - struct flock lock; - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 1; - return 0 == fcntl (fd, F_SETLK, &lock); -} - -inline int open_or_create_and_lock_file(const char *name) -{ - permissions p; - p.set_unrestricted(); - while(1){ - int fd = create_or_open_file(name, read_write, p); - if(fd < 0){ - return fd; - } - if(!try_lock_locking_file(fd)){ - close(fd); - return -1; - } - struct stat s; - if(0 == stat(name, &s)){ - return fd; - } - else{ - close(fd); - } - } -} - -inline int try_open_and_lock_file(const char *name) -{ - int fd = open_existing_file(name, read_write); - if(fd < 0){ - return fd; - } - if(!try_lock_locking_file(fd)){ - close(fd); - return -1; - } - return fd; -} - -inline void close_lock_file(int fd) -{ close(fd); } - -inline bool is_valid_fd(int fd) -{ - struct stat s; - return EBADF != fstat(fd, &s); -} - -inline bool is_normal_file(int fd) -{ - struct stat s; - if(0 != fstat(fd, &s)) - return false; - return 0 != (s.st_mode & S_IFREG); -} - -inline std::size_t get_size(int fd) -{ - struct stat s; - if(0 != fstat(fd, &s)) - return 0u; - return (std::size_t)s.st_size; -} - -inline bool fill_file_serial_id(int fd, locking_file_serial_id &id) -{ - struct stat s; - if(0 != fstat(fd, &s)) - return false; - id.fd = fd; - id.st_dev = s.st_dev; - id.st_ino = s.st_ino; - id.modules_attached_to_gmem_count = 1; //Initialize attached count - return true; -} - -inline bool compare_file_serial(int fd, const locking_file_serial_id &id) -{ - struct stat info; - if(0 != fstat(fd, &info)) - return false; - - return id.st_dev == info.st_dev && - id.st_ino == info.st_ino; -} - -#endif - -template<class ManagedShMem> -struct gmem_erase_func -{ - gmem_erase_func(const char *shm_name, const char *singleton_lock_file_path, ManagedShMem & shm) - :shm_name_(shm_name), singleton_lock_file_path_(singleton_lock_file_path), shm_(shm) - {} - - void operator()() - { - locking_file_serial_id *pserial_id = shm_.template find<locking_file_serial_id>("lock_file_fd").first; - if(pserial_id){ - pserial_id->fd = GMemMarkToBeRemoved; - } - delete_file(singleton_lock_file_path_); - shared_memory_object::remove(shm_name_); - } - - const char * const shm_name_; - const char * const singleton_lock_file_path_; - ManagedShMem & shm_; -}; - -//This function applies shared memory erasure logic based on the passed lock file. -template<class ManagedShMem> -void managed_sh_dependant<ManagedShMem>:: - apply_gmem_erase_logic(const char *filepath, const char *filename) -{ - int fd = GMemMarkToBeRemoved; - try{ - std::string str; - //If the filename is current process lock file, then avoid it - if(file_locking_helpers::check_if_filename_complies_with_pid - (filename, get_lock_file_base_name(), get_current_process_id(), str, true)){ - return; - } - //Open and lock the other process' lock file - fd = try_open_and_lock_file(filepath); - if(fd < 0){ - return; - } - //If done, then the process is dead so take global shared memory name - //(the name is based on the lock file name) and try to apply erasure logic - str.insert(0, get_shm_base_name()); - try{ - ManagedShMem shm(open_only, str.c_str()); - gmem_erase_func<ManagedShMem> func(str.c_str(), filepath, shm); - shm.try_atomic_func(func); - } - catch(interprocess_exception &e){ - //If shared memory is not found erase the lock file - if(e.get_error_code() == not_found_error){ - delete_file(filepath); - } - } - } - catch(...){ - - } - if(fd >= 0){ - close_lock_file(fd); - } -} - -} //namespace intermodule_singleton_helpers { - - - -namespace intermodule_singleton_helpers { - -//The lock file logic creates uses a unique instance to a file -template <class ManagedShMem> -struct lock_file_logic -{ - lock_file_logic(ManagedShMem &shm) - : mshm(shm) - { shm.atomic_func(*this); } - - void operator()(void) - { - retry_with_new_shm = false; - - //First find the file locking descriptor id - locking_file_serial_id *pserial_id = - mshm.template find<locking_file_serial_id>("lock_file_fd").first; - - int fd; - //If not found schedule a creation - if(!pserial_id){ - fd = GMemNotPresent; - } - //Else get it - else{ - fd = pserial_id->fd; - } - //If we need to create a new one, do it - if(fd == GMemNotPresent){ - std::string lck_str; - //Create a unique current pid based lock file path - create_and_get_singleton_lock_file_path(lck_str); - //Open or create and lock file - int fd = intermodule_singleton_helpers::open_or_create_and_lock_file(lck_str.c_str()); - //If failed, write a bad file descriptor to notify other modules that - //something was wrong and unlink shared memory. Mark the function object - //to tell caller to retry with another shared memory - if(fd < 0){ - this->register_lock_file(GMemMarkToBeRemoved); - std::string s; - get_shm_name(s); - shared_memory_object::remove(s.c_str()); - retry_with_new_shm = true; - } - //If successful, register the file descriptor - else{ - this->register_lock_file(fd); - } - } - //If the fd was invalid (maybe a previous try failed) notify caller that - //should retry creation logic, since this shm might have been already - //unlinked since the shm was removed - else if (fd == GMemMarkToBeRemoved){ - retry_with_new_shm = true; - } - //If the stored fd is not valid (a open fd, a normal file with the - //expected size, or does not have the same file id number, - //then it's an old shm from an old process with the same pid. - //If that's the case, mark it as invalid - else if(!is_valid_fd(fd) || - !is_normal_file(fd) || - 0 != get_size(fd) || - !compare_file_serial(fd, *pserial_id)){ - pserial_id->fd = GMemMarkToBeRemoved; - std::string s; - get_shm_name(s); - shared_memory_object::remove(s.c_str()); - retry_with_new_shm = true; - } - else{ - //If the lock file is ok, increment reference count of - //attached modules to shared memory - atomic_inc32(&pserial_id->modules_attached_to_gmem_count); - } - } - - private: - locking_file_serial_id * register_lock_file(int fd) - { - locking_file_serial_id *pinfo = mshm.template construct<locking_file_serial_id>("lock_file_fd")(); - fill_file_serial_id(fd, *pinfo); - return pinfo; - } - - public: - ManagedShMem &mshm; - bool retry_with_new_shm; -}; - -#if defined(BOOST_INTERPROCESS_WINDOWS) - -template<> -struct lock_file_logic<windows_managed_global_memory> -{ - lock_file_logic(windows_managed_global_memory &) - : retry_with_new_shm(false) - {} - - void operator()(void){} - const bool retry_with_new_shm; -}; - -#endif - -} //namespace intermodule_singleton_helpers { - -//This class contains common code for all singleton types, so that we instantiate this -//code just once per module. This class also holds a reference counted shared memory -//to be used by all instances - -template<class ManagedShMem> -class intermodule_singleton_common -{ - public: - typedef void*(singleton_constructor_t)(ManagedShMem &); - typedef void (singleton_destructor_t)(void *, ManagedShMem &); - - static const ::boost::uint32_t Uninitialized = 0u; - static const ::boost::uint32_t Initializing = 1u; - static const ::boost::uint32_t Initialized = 2u; - static const ::boost::uint32_t Broken = 3u; - - static void finalize_singleton_logic(void *ptr, singleton_destructor_t destructor) - { - if(ptr) - destructor(ptr, get_shm()); - //If this is the last singleton of this module - //apply shm destruction. - //Note: singletons are destroyed when the module is unloaded - //so no threads should be executing or holding references - //to this module - if(1 == atomic_dec32(&this_module_singleton_count)){ - destroy_shm(); - } - } - - static void initialize_singleton_logic - (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t ini_func); - - private: - static ManagedShMem &get_shm() - { - return *static_cast<ManagedShMem *>(static_cast<void *>(&mem_holder.shm_mem)); - } - - static void initialize_shm(); - static void destroy_shm(); - //Static data, zero-initalized without any dependencies - //this_module_singleton_count is the number of singletons used by this module - static volatile boost::uint32_t this_module_singleton_count; - //this_module_shm_initialized is the state of this module's shm class object - static volatile boost::uint32_t this_module_shm_initialized; - static struct mem_holder_t - { - ::boost::detail::max_align aligner; - char shm_mem [sizeof(ManagedShMem)]; - } mem_holder; -}; - -template<class ManagedShMem> -volatile boost::uint32_t intermodule_singleton_common<ManagedShMem>::this_module_singleton_count; - -template<class ManagedShMem> -volatile boost::uint32_t intermodule_singleton_common<ManagedShMem>::this_module_shm_initialized; - -template<class ManagedShMem> -typename intermodule_singleton_common<ManagedShMem>::mem_holder_t - intermodule_singleton_common<ManagedShMem>::mem_holder; - -template<class ManagedShMem> -void intermodule_singleton_common<ManagedShMem>::initialize_shm() -{ - //Obtain unique shm name and size - std::string s; - while(1){ - //Try to pass shm state to initializing - ::boost::uint32_t tmp = atomic_cas32(&this_module_shm_initialized, Initializing, Uninitialized); - if(tmp >= Initialized){ - break; - } - //If some other thread is doing the work wait - else if(tmp == Initializing){ - thread_yield(); - } - else{ //(tmp == Uninitialized) - //If not initialized try it again? - try{ - //Remove old shared memory from the system - intermodule_singleton_helpers::managed_sh_dependant<ManagedShMem>::remove_old_gmem(); - // - if(s.empty()){ - intermodule_singleton_helpers::get_shm_name(s); - } - const char *ShmName = s.c_str(); - const std::size_t ShmSize = intermodule_singleton_helpers::get_shm_size();; - - //in-place construction of the shared memory class - ::new (&get_shm())ManagedShMem(open_or_create, ShmName, ShmSize); - //Use shared memory internal lock to initialize the lock file - //that will mark this gmem as "in use". - intermodule_singleton_helpers::lock_file_logic<ManagedShMem> f(get_shm()); - //If function failed (maybe a competing process has erased the shared - //memory between creation and file locking), retry with a new instance. - if(f.retry_with_new_shm){ - get_shm().~ManagedShMem(); - atomic_write32(&this_module_shm_initialized, Uninitialized); - } - else{ - //Locking succeeded, so this shared memory module-instance is ready - atomic_write32(&this_module_shm_initialized, Initialized); - break; - } - } - catch(...){ - // - throw; - } - } - } -} - -template<class ManagedShMem> -struct unlink_shmlogic -{ - unlink_shmlogic(ManagedShMem &mshm) - : mshm_(mshm) - { mshm.atomic_func(*this); } - void operator()() - { - intermodule_singleton_helpers::locking_file_serial_id *pserial_id = - mshm_.template find<intermodule_singleton_helpers::locking_file_serial_id> - ("lock_file_fd").first; - BOOST_ASSERT(0 != pserial_id); - if(1 == atomic_dec32(&pserial_id->modules_attached_to_gmem_count)){ - int fd = pserial_id->fd; - if(fd > 0){ - pserial_id->fd = intermodule_singleton_helpers::GMemMarkToBeRemoved; - std::string s; - intermodule_singleton_helpers::create_and_get_singleton_lock_file_path(s); - delete_file(s.c_str()); - intermodule_singleton_helpers::close_lock_file(fd); - intermodule_singleton_helpers::get_shm_name(s); - shared_memory_object::remove(s.c_str()); - } - } - } - ManagedShMem &mshm_; -}; - -#if defined(BOOST_INTERPROCESS_WINDOWS) - -template<> -struct unlink_shmlogic<windows_managed_global_memory> -{ - unlink_shmlogic(windows_managed_global_memory &) - {} - void operator()(){} -}; - -#endif - - -template<class ManagedShMem> -void intermodule_singleton_common<ManagedShMem>::destroy_shm() -{ - if(!atomic_read32(&this_module_singleton_count)){ - //This module is being unloaded, so destroy - //the shared memory object of this module - //and unlink the shared memory if it's the last - unlink_shmlogic<ManagedShMem> f(get_shm()); - (get_shm()).~ManagedShMem(); - atomic_write32(&this_module_shm_initialized, Uninitialized); - //Do some cleanup for other processes old gmem instances - intermodule_singleton_helpers::managed_sh_dependant<ManagedShMem>::remove_old_gmem(); - } -} - -//Initialize this_module_singleton_ptr, creates the shared memory if needed and also creates an unique -//opaque type in shared memory through a singleton_constructor_t function call, -//initializing the passed pointer to that unique instance. -// -//We have two concurrency types here. a)the shared memory/singleton creation must -//be safe between threads of this process but in different modules/dlls. b) -//the pointer to the singleton is per-module, so we have to protect this -//initization between threads of the same module. -// -//All static variables declared here are shared between inside a module -//so atomic operations will synchronize only threads of the same module. -template<class ManagedShMem> -void intermodule_singleton_common<ManagedShMem>::initialize_singleton_logic - (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t constructor) -{ - //If current module is not initialized enter to lock free logic - if(atomic_read32(&this_module_singleton_initialized) != Initialized){ - //Now a single thread of the module will succeed in this CAS. - //trying to pass from Uninitialized to Initializing - ::boost::uint32_t previous_module_singleton_initialized = atomic_cas32 - (&this_module_singleton_initialized, Initializing, Uninitialized); - //If the thread succeeded the CAS (winner) it will compete with other - //winner threads from other modules to create the shared memory - if(previous_module_singleton_initialized == Uninitialized){ - try{ - //Now initialize shm, this function solves concurrency issues - //between threads of several modules - initialize_shm(); - //Increment the module reference count that reflects how many - //singletons this module holds, so that we can safely destroy - //module shared memory object when no singleton is left - atomic_inc32(&this_module_singleton_count); - //Now try to create the singleton in shared memory. - //This function solves concurrency issues - //between threads of several modules - void *tmp = constructor(get_shm()); - //Insert a barrier before assigning the pointer to - //make sure this assignment comes after the initialization - atomic_write32(&this_module_singleton_initialized, Initializing); - //Assign the singleton address to the module-local pointer - ptr = tmp; - //Memory barrier inserted, all previous operations should complete - //before this one. Now marked as initialized - atomic_inc32(&this_module_singleton_initialized); - } - catch(...){ - //Mark singleton failed to initialize - atomic_write32(&this_module_singleton_initialized, Broken); - throw; - } - } - //If previous state was initializing, this means that another winner thread is - //trying to initialize the singleton. Just wait until completes its work. - else if(previous_module_singleton_initialized == Initializing){ - while(1){ - previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized); - if(previous_module_singleton_initialized >= Initialized){ - //Already initialized, or exception thrown by initializer thread - break; - } - else if(previous_module_singleton_initialized == Initializing){ - thread_yield(); - } - else{ - //This can't be happening! - BOOST_ASSERT(0); - } - } - } - else if(previous_module_singleton_initialized == Initialized){ - //Nothing to do here, the singleton is ready - } - //If previous state was greater than initialized, then memory is broken - //trying to initialize the singleton. - else{//(previous_module_singleton_initialized > Initialized) - throw interprocess_exception("boost::interprocess::intermodule_singleton initialization failed"); - } - } - BOOST_ASSERT(ptr != 0); -} - -//Now this class is a singleton, initializing the singleton in -//the first get() function call if LazyInit is false. If true -//then the singleton will be initialized when loading the module. -template<typename C, bool LazyInit, class ManagedShMem> -class intermodule_singleton_impl -{ - public: - static C& get() //Let's make inlining easy - { - if(!this_module_singleton_ptr){ - if(lifetime.dummy_function()) //This forces lifetime instantiation, for reference counted destruction - intermodule_singleton_common<ManagedShMem>::initialize_singleton_logic - (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor); - } - return *static_cast<C*>(this_module_singleton_ptr); - } - - private: - - struct ref_count_ptr - { - ref_count_ptr(C *p, boost::uint32_t count) - : ptr(p), singleton_ref_count(count) - {} - C *ptr; - //This reference count serves to count the number of attached - //modules to this singleton - volatile boost::uint32_t singleton_ref_count; - }; - - //These statics will be zero-initialized without any constructor call dependency - //this_module_singleton_ptr will be a module-local pointer to the singleton - static void* this_module_singleton_ptr; - //this_module_singleton_count will be used to synchronize threads of the same module - //for access to a singleton instance, and to flag the state of the - //singleton. - static volatile boost::uint32_t this_module_singleton_initialized; - - //This class destructor will trigger singleton destruction - struct lifetime_type_lazy - { - bool dummy_function() - { return m_dummy == 0; } - - ~lifetime_type_lazy() - { - intermodule_singleton_common<ManagedShMem>::finalize_singleton_logic - (this_module_singleton_ptr, singleton_destructor); - } - //Dummy volatile so that the compiler can't resolve its value at compile-time - //and can't avoid lifetime_type instantiation if dummy_function() is called. - static volatile int m_dummy; - }; - - struct lifetime_type_static - : public lifetime_type_lazy - { - lifetime_type_static() - { - intermodule_singleton_common<ManagedShMem>::initialize_singleton_logic - (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor); - } - }; - - typedef typename if_c - <LazyInit, lifetime_type_lazy, lifetime_type_static>::type lifetime_type; - - static lifetime_type lifetime; - - //A functor to be executed inside shared memory lock that just - //searches for the singleton in shm and if not present creates a new one. - //If singleton constructor throws, the exception is propagated - struct init_atomic_func - { - init_atomic_func(ManagedShMem &m) - : mshm(m) - {} - - void operator()() - { - ref_count_ptr *rcount = mshm.template find<ref_count_ptr>(unique_instance).first; - if(!rcount){ - C *p = new C(); - try{ - rcount = mshm.template construct<ref_count_ptr>(unique_instance)(p, 0u); - } - catch(...){ - delete p; - throw; - } - } - atomic_inc32(&rcount->singleton_ref_count); - ret_ptr = rcount->ptr; - } - ManagedShMem &mshm; - void *ret_ptr; - }; - - //A functor to be executed inside shared memory lock that just - //deletes the singleton in shm if the attached count reaches to zero - struct fini_atomic_func - { - fini_atomic_func(ManagedShMem &m) - : mshm(m) - {} - - void operator()() - { - ref_count_ptr *rcount = mshm.template find<ref_count_ptr>(unique_instance).first; - //The object must exist - BOOST_ASSERT(rcount); - //Check if last reference - if(atomic_dec32(&rcount->singleton_ref_count) == 1){ - //If last, destroy the object - BOOST_ASSERT(rcount->ptr != 0); - delete rcount->ptr; - //Now destroy shm entry - bool destroyed = mshm.template destroy<ref_count_ptr>(unique_instance); - (void)destroyed; BOOST_ASSERT(destroyed == true); - } - } - ManagedShMem &mshm; - void *ret_ptr; - }; - - //A wrapper to execute init_atomic_func - static void *singleton_constructor(ManagedShMem &mshm) - { - init_atomic_func f(mshm); - mshm.atomic_func(f); - return f.ret_ptr; - } - - //A wrapper to execute fini_atomic_func - static void singleton_destructor(void *p, ManagedShMem &mshm) - { (void)p; - fini_atomic_func f(mshm); - mshm.atomic_func(f); - } -}; - -template <typename C, bool L, class ManagedShMem> -volatile int intermodule_singleton_impl<C, L, ManagedShMem>::lifetime_type_lazy::m_dummy = 0; - -//These will be zero-initialized by the loader -template <typename C, bool L, class ManagedShMem> -void *intermodule_singleton_impl<C, L, ManagedShMem>::this_module_singleton_ptr = 0; - -template <typename C, bool L, class ManagedShMem> -volatile boost::uint32_t intermodule_singleton_impl<C, L, ManagedShMem>::this_module_singleton_initialized = 0; - -template <typename C, bool L, class ManagedShMem> -typename intermodule_singleton_impl<C, L, ManagedShMem>::lifetime_type - intermodule_singleton_impl<C, L, ManagedShMem>::lifetime; - -template<typename C, bool LazyInit = false> -class portable_intermodule_singleton - : public intermodule_singleton_impl<C, LazyInit, managed_global_memory> -{}; - -#if defined(BOOST_INTERPROCESS_WINDOWS) - -template<typename C, bool LazyInit = false> -class windows_intermodule_singleton - : public intermodule_singleton_impl - < C - , LazyInit - , windows_managed_global_memory - > -{}; - -#endif - //Now this class is a singleton, initializing the singleton in //the first get() function call if LazyInit is false. If true //then the singleton will be initialized when loading the module. -template<typename C, bool LazyInit = false> +template<typename C, bool LazyInit = true, bool Phoenix = true> class intermodule_singleton #ifdef BOOST_INTERPROCESS_WINDOWS - : public windows_intermodule_singleton<C, LazyInit> + : public windows_intermodule_singleton<C, LazyInit, Phoenix> #else - : public portable_intermodule_singleton<C, LazyInit> + : public portable_intermodule_singleton<C, LazyInit, Phoenix> #endif {}; - } //namespace ipcdetail{ } //namespace interprocess{ } //namespace boost{ diff --git a/boost/interprocess/detail/intermodule_singleton_common.hpp b/boost/interprocess/detail/intermodule_singleton_common.hpp new file mode 100644 index 0000000000..0710c0bbc1 --- /dev/null +++ b/boost/interprocess/detail/intermodule_singleton_common.hpp @@ -0,0 +1,495 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP +#define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP + +#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> + +#include <boost/interprocess/detail/atomic.hpp> +#include <boost/interprocess/detail/os_thread_functions.hpp> +#include <boost/type_traits/type_with_alignment.hpp> +#include <boost/interprocess/detail/mpl.hpp> +#include <boost/assert.hpp> +#include <cstddef> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <string> +#include <sstream> + +namespace boost{ +namespace interprocess{ +namespace ipcdetail{ + +namespace intermodule_singleton_helpers { + +inline void get_pid_creation_time_str(std::string &s) +{ + std::stringstream stream; + stream << get_current_process_id() << '_'; + stream.precision(6); + stream << std::fixed << get_current_process_creation_time(); + s = stream.str(); +} + +inline const char *get_map_base_name() +{ return "bip.gmem.map."; } + +inline void get_map_name(std::string &map_name) +{ + get_pid_creation_time_str(map_name); + map_name.insert(0, get_map_base_name()); +} + +inline std::size_t get_map_size() +{ return 65536; } + +template<class ThreadSafeGlobalMap> +struct thread_safe_global_map_dependant; + +} //namespace intermodule_singleton_helpers { + +//This class contains common code for all singleton types, so that we instantiate this +//code just once per module. This class also holds a thread soafe global map +//to be used by all instances protected with a reference count +template<class ThreadSafeGlobalMap> +class intermodule_singleton_common +{ + public: + typedef void*(singleton_constructor_t)(ThreadSafeGlobalMap &); + typedef void (singleton_destructor_t)(void *, ThreadSafeGlobalMap &); + + static const ::boost::uint32_t Uninitialized = 0u; + static const ::boost::uint32_t Initializing = 1u; + static const ::boost::uint32_t Initialized = 2u; + static const ::boost::uint32_t Broken = 3u; + static const ::boost::uint32_t Destroyed = 4u; + + //Initialize this_module_singleton_ptr, creates the global map if needed and also creates an unique + //opaque type in global map through a singleton_constructor_t function call, + //initializing the passed pointer to that unique instance. + // + //We have two concurrency types here. a)the global map/singleton creation must + //be safe between threads of this process but in different modules/dlls. b) + //the pointer to the singleton is per-module, so we have to protect this + //initization between threads of the same module. + // + //All static variables declared here are shared between inside a module + //so atomic operations will synchronize only threads of the same module. + static void initialize_singleton_logic + (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t constructor, bool phoenix) + { + //If current module is not initialized enter to lock free logic + if(atomic_read32(&this_module_singleton_initialized) != Initialized){ + //Now a single thread of the module will succeed in this CAS. + //trying to pass from Uninitialized to Initializing + ::boost::uint32_t previous_module_singleton_initialized = atomic_cas32 + (&this_module_singleton_initialized, Initializing, Uninitialized); + //If the thread succeeded the CAS (winner) it will compete with other + //winner threads from other modules to create the global map + if(previous_module_singleton_initialized == Destroyed){ + //Trying to resurrect a dead Phoenix singleton. Just try to + //mark it as uninitialized and start again + if(phoenix){ + atomic_cas32(&this_module_singleton_initialized, Uninitialized, Destroyed); + previous_module_singleton_initialized = atomic_cas32 + (&this_module_singleton_initialized, Initializing, Uninitialized); + } + //Trying to resurrect a non-Phoenix dead singleton is an error + else{ + throw interprocess_exception("Boost.Interprocess: Dead reference on non-Phoenix singleton of type"); + } + } + if(previous_module_singleton_initialized == Uninitialized){ + try{ + //Now initialize the global map, this function must solve concurrency + //issues between threads of several modules + initialize_global_map_handle(); + //Now try to create the singleton in global map. + //This function solves concurrency issues + //between threads of several modules + void *tmp = constructor(get_map()); + //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 + atomic_inc32(&this_module_singleton_count); + //Insert a barrier before assigning the pointer to + //make sure this assignment comes after the initialization + atomic_write32(&this_module_singleton_initialized, Initializing); + //Assign the singleton address to the module-local pointer + ptr = tmp; + //Memory barrier inserted, all previous operations should complete + //before this one. Now marked as initialized + atomic_write32(&this_module_singleton_initialized, Initialized); + } + catch(...){ + //Mark singleton failed to initialize + atomic_write32(&this_module_singleton_initialized, Broken); + throw; + } + } + //If previous state was initializing, this means that another winner thread is + //trying to initialize the singleton. Just wait until completes its work. + else if(previous_module_singleton_initialized == Initializing){ + while(1){ + previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized); + if(previous_module_singleton_initialized >= Initialized){ + //Already initialized, or exception thrown by initializer thread + break; + } + else if(previous_module_singleton_initialized == Initializing){ + thread_yield(); + } + else{ + //This can't be happening! + BOOST_ASSERT(0); + } + } + } + else if(previous_module_singleton_initialized == Initialized){ + //Nothing to do here, the singleton is ready + } + //If previous state was greater than initialized, then memory is broken + //trying to initialize the singleton. + else{//(previous_module_singleton_initialized > Initialized) + throw interprocess_exception("boost::interprocess::intermodule_singleton initialization failed"); + } + } + BOOST_ASSERT(ptr != 0); + } + + static void finalize_singleton_logic(void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_destructor_t destructor) + { + //Protect destruction against lazy singletons not initialized in this execution + if(ptr){ + //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()); + ptr = 0; + + //Memory barrier to make sure pointer is nulled. + //Mark this singleton as destroyed. + atomic_write32(&this_module_singleton_initialized, Destroyed); + + //If this is the last singleton of this module + //apply map destruction. + //Note: singletons are destroyed when the module is unloaded + //so no threads should be executing or holding references + //to this module + if(1 == atomic_dec32(&this_module_singleton_count)){ + destroy_global_map_handle(); + } + } + } + + private: + static ThreadSafeGlobalMap &get_map() + { + return *static_cast<ThreadSafeGlobalMap *>(static_cast<void *>(&mem_holder.map_mem)); + } + + static void initialize_global_map_handle() + { + //Obtain unique map name and size + while(1){ + //Try to pass map state to initializing + ::boost::uint32_t tmp = atomic_cas32(&this_module_map_initialized, Initializing, Uninitialized); + if(tmp == Initialized || tmp == Broken){ + break; + } + else if(tmp == Destroyed){ + tmp = atomic_cas32(&this_module_map_initialized, Uninitialized, Destroyed); + continue; + } + //If some other thread is doing the work wait + else if(tmp == Initializing){ + thread_yield(); + } + else{ //(tmp == Uninitialized) + //If not initialized try it again? + try{ + //Remove old 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 + intermodule_singleton_helpers::thread_safe_global_map_dependant + <ThreadSafeGlobalMap>::construct_map(static_cast<void*>(&get_map())); + //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()); + //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(); + atomic_write32(&this_module_map_initialized, Destroyed); + } + else{ + //Locking succeeded, so this global map module-instance is ready + atomic_write32(&this_module_map_initialized, Initialized); + break; + } + } + catch(...){ + // + throw; + } + } + } + } + + static void destroy_global_map_handle() + { + if(!atomic_read32(&this_module_singleton_count)){ + //This module is being unloaded, so destroy + //the global map object of this module + //and unlink the global map if it's the last + typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>:: + unlink_map_logic f(get_map()); + (get_map()).~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(); + } + } + + //Static data, zero-initalized without any dependencies + //this_module_singleton_count is the number of singletons used by this module + static volatile boost::uint32_t this_module_singleton_count; + + //this_module_map_initialized is the state of this module's map class object. + //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 + { + ::boost::detail::max_align aligner; + char map_mem [sizeof(ThreadSafeGlobalMap)]; + } mem_holder; +}; + +template<class ThreadSafeGlobalMap> +volatile boost::uint32_t intermodule_singleton_common<ThreadSafeGlobalMap>::this_module_singleton_count; + +template<class ThreadSafeGlobalMap> +volatile boost::uint32_t intermodule_singleton_common<ThreadSafeGlobalMap>::this_module_map_initialized; + +template<class ThreadSafeGlobalMap> +typename intermodule_singleton_common<ThreadSafeGlobalMap>::mem_holder_t + intermodule_singleton_common<ThreadSafeGlobalMap>::mem_holder; + +//A reference count to be stored in global map holding the number +//of singletons (one per module) attached to the instance pointed by +//the internal ptr. +struct ref_count_ptr +{ + ref_count_ptr(void *p, boost::uint32_t count) + : ptr(p), singleton_ref_count(count) + {} + void *ptr; + //This reference count serves to count the number of attached + //modules to this singleton + volatile boost::uint32_t singleton_ref_count; +}; + + +//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, bool Phoenix, class ThreadSafeGlobalMap> +class intermodule_singleton_impl +{ + public: + + static C& get() //Let's make inlining easy + { + if(!this_module_singleton_ptr){ + if(lifetime.dummy_function()){ //This forces lifetime instantiation, for reference counted destruction + atentry_work(); + } + } + return *static_cast<C*>(this_module_singleton_ptr); + } + + private: + + static void atentry_work() + { + intermodule_singleton_common<ThreadSafeGlobalMap>::initialize_singleton_logic + (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor, Phoenix); + } + + static void atexit_work() + { + intermodule_singleton_common<ThreadSafeGlobalMap>::finalize_singleton_logic + (this_module_singleton_ptr, this_module_singleton_initialized, singleton_destructor); + } + + //These statics will be zero-initialized without any constructor call dependency + //this_module_singleton_ptr will be a module-local pointer to the singleton + static void* this_module_singleton_ptr; + + //this_module_singleton_count will be used to synchronize threads of the same module + //for access to a singleton instance, and to flag the state of the + //singleton. + static volatile boost::uint32_t this_module_singleton_initialized; + + //This class destructor will trigger singleton destruction + struct lifetime_type_lazy + { + bool dummy_function() + { return m_dummy == 0; } + + ~lifetime_type_lazy() + { + if(!Phoenix){ + atexit_work(); + } + } + + //Dummy volatile so that the compiler can't resolve its value at compile-time + //and can't avoid lifetime_type instantiation if dummy_function() is called. + static volatile int m_dummy; + }; + + struct lifetime_type_static + : public lifetime_type_lazy + { + lifetime_type_static() + { atentry_work(); } + }; + + typedef typename if_c + <LazyInit, lifetime_type_lazy, lifetime_type_static>::type lifetime_type; + + static lifetime_type lifetime; + + //A functor to be executed inside global map lock that just + //searches for the singleton in map and if not present creates a new one. + //If singleton constructor throws, the exception is propagated + struct init_atomic_func + { + init_atomic_func(ThreadSafeGlobalMap &m) + : m_map(m) + {} + + void operator()() + { + ref_count_ptr *rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant + <ThreadSafeGlobalMap>::find(m_map, typeid(C).name()); + if(!rcount){ + C *p = new C; + try{ + ref_count_ptr val(p, 0u); + rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant + <ThreadSafeGlobalMap>::insert(m_map, typeid(C).name(), val); + } + catch(...){ + intermodule_singleton_helpers::thread_safe_global_map_dependant + <ThreadSafeGlobalMap>::erase(m_map, typeid(C).name()); + delete p; + throw; + } + } + if(Phoenix){ + std::atexit(&atexit_work); + } + atomic_inc32(&rcount->singleton_ref_count); + ret_ptr = rcount->ptr; + } + void *data() const + { return ret_ptr; } + + private: + ThreadSafeGlobalMap &m_map; + void *ret_ptr; + }; + + //A functor to be executed inside global map lock that just + //deletes the singleton in map if the attached count reaches to zero + struct fini_atomic_func + { + fini_atomic_func(ThreadSafeGlobalMap &m) + : m_map(m) + {} + + void operator()() + { + ref_count_ptr *rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant + <ThreadSafeGlobalMap>::find(m_map, typeid(C).name()); + //The object must exist + BOOST_ASSERT(rcount); + BOOST_ASSERT(rcount->singleton_ref_count > 0); + //Check if last reference + if(atomic_dec32(&rcount->singleton_ref_count) == 1){ + //If last, destroy the object + BOOST_ASSERT(rcount->ptr != 0); + C *pc = static_cast<C*>(rcount->ptr); + //Now destroy map entry + bool destroyed = intermodule_singleton_helpers::thread_safe_global_map_dependant + <ThreadSafeGlobalMap>::erase(m_map, typeid(C).name()); + (void)destroyed; BOOST_ASSERT(destroyed == true); + delete pc; + } + } + void *data() const + { return ret_ptr; } + + private: + ThreadSafeGlobalMap &m_map; + void *ret_ptr; + }; + + //A wrapper to execute init_atomic_func + static void *singleton_constructor(ThreadSafeGlobalMap &map) + { + init_atomic_func f(map); + intermodule_singleton_helpers::thread_safe_global_map_dependant + <ThreadSafeGlobalMap>::atomic_func(map, f); + return f.data(); + } + + //A wrapper to execute fini_atomic_func + static void singleton_destructor(void *p, ThreadSafeGlobalMap &map) + { (void)p; + fini_atomic_func f(map); + intermodule_singleton_helpers::thread_safe_global_map_dependant + <ThreadSafeGlobalMap>::atomic_func(map, f); + } +}; + +template <typename C, bool L, bool P, class ThreadSafeGlobalMap> +volatile int intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime_type_lazy::m_dummy = 0; + +//These will be zero-initialized by the loader +template <typename C, bool L, bool P, class ThreadSafeGlobalMap> +void *intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::this_module_singleton_ptr = 0; + +template <typename C, bool L, bool P, class ThreadSafeGlobalMap> +volatile boost::uint32_t intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::this_module_singleton_initialized = 0; + +template <typename C, bool L, bool P, class ThreadSafeGlobalMap> +typename intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime_type + intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime; + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP diff --git a/boost/interprocess/detail/intersegment_ptr.hpp b/boost/interprocess/detail/intersegment_ptr.hpp index 92970923d0..16d3505883 100644 --- a/boost/interprocess/detail/intersegment_ptr.hpp +++ b/boost/interprocess/detail/intersegment_ptr.hpp @@ -68,8 +68,8 @@ struct intersegment_base static const std::size_t begin_bits = max_segment_size_bits - align_bits; static const std::size_t pow_size_bits_helper = static_log2<max_segment_size_bits>::value; - static const std::size_t pow_size_bits = - (max_segment_size_bits == (std::size_t(1) << pow_size_bits_helper)) ? + static const std::size_t pow_size_bits = + (max_segment_size_bits == (std::size_t(1) << pow_size_bits_helper)) ? pow_size_bits_helper : pow_size_bits_helper + 1; static const std::size_t frc_size_bits = size_t_bits - ctrl_bits - begin_bits - pow_size_bits; @@ -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; } @@ -185,7 +185,7 @@ struct intersegment_base //!null pointer bool is_null() const { - return (this->get_mode() < is_relative) && + return (this->get_mode() < is_relative) && !members.direct.dummy && !members.direct.addr; } @@ -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); @@ -340,7 +340,7 @@ struct flat_map_intersegment } } - //!Sets the object internals to represent the address pointed + //!Sets the object internals to represent the address pointed //!by another flat_map_intersegment void set_from_other(const self_t &other) { @@ -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) @@ -434,7 +434,7 @@ struct flat_map_intersegment typedef set<segment_group_t> segment_groups_t; typedef boost::interprocess::flat_map - <const void * + <const void * ,segment_info_t ,std::less<const void *> > ptr_to_segment_info_t; @@ -443,9 +443,9 @@ struct flat_map_intersegment //!Mutex to preserve integrity in multi-threaded //!enviroments typedef Mutex mutex_type; - //!Maps base addresses and segment information + //!Maps base addresses and segment information //!(size and segment group and id)* - + ptr_to_segment_info_t m_ptr_to_segment_info; ~mappings_t() @@ -476,7 +476,7 @@ struct flat_map_intersegment return; } //Find the first base address greater than ptr - typename ptr_to_segment_info_t::iterator it + typename ptr_to_segment_info_t::iterator it = s_map.m_ptr_to_segment_info.upper_bound(ptr); if(it == s_map.m_ptr_to_segment_info.begin()){ segment = segment_info_t(); @@ -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,23 +574,23 @@ struct flat_map_intersegment } } return success; - } + } } }; //!Static map-segment_info associated with //!flat_map_intersegment<> template <class Mutex> -typename flat_map_intersegment<Mutex>::mappings_t +typename flat_map_intersegment<Mutex>::mappings_t flat_map_intersegment<Mutex>::s_map; //!Static segment group container associated with //!flat_map_intersegment<> template <class Mutex> -typename flat_map_intersegment<Mutex>::segment_groups_t +typename flat_map_intersegment<Mutex>::segment_groups_t flat_map_intersegment<Mutex>::s_groups; -//!A smart pointer that can point to a pointee that resides in another memory +//!A smart pointer that can point to a pointee that resides in another memory //!memory mapped or shared memory segment. template <class T> class intersegment_ptr : public flat_map_intersegment<interprocess_mutex> @@ -623,13 +623,13 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex> //!Constructor from other intersegment_ptr //!Never throws - intersegment_ptr(const intersegment_ptr& ptr) + intersegment_ptr(const intersegment_ptr& ptr) { base_t::set_from_other(ptr); } - //!Constructor from other intersegment_ptr. If pointers of pointee types are + //!Constructor from other intersegment_ptr. If pointers of pointee types are //!convertible, intersegment_ptrs will be convertibles. Never throws. template<class T2> - intersegment_ptr(const intersegment_ptr<T2> &ptr) + intersegment_ptr(const intersegment_ptr<T2> &ptr) { pointer p(ptr.get()); (void)p; base_t::set_from_other(ptr); } //!Emulates static_cast operator. @@ -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 + //!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). @@ -686,19 +686,19 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex> intersegment_ptr& operator= (const intersegment_ptr &ptr) { base_t::set_from_other(ptr); return *this; } - //!Assignment from related intersegment_ptr. If pointers of pointee types + //!Assignment from related intersegment_ptr. If pointers of pointee types //!are assignable, intersegment_ptrs will be assignable. Never throws. template <class T2> intersegment_ptr& operator= (const intersegment_ptr<T2> & ptr) - { - pointer p(ptr.get()); (void)p; - base_t::set_from_other(ptr); return *this; + { + pointer p(ptr.get()); (void)p; + base_t::set_from_other(ptr); return *this; } - + //!intersegment_ptr + std::ptrdiff_t. //!Never throws. - intersegment_ptr operator+ (std::ptrdiff_t idx) const - { + intersegment_ptr 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; @@ -727,7 +727,7 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex> //!Never throws. intersegment_ptr& operator++ (void) { base_t::inc_offset(sizeof(T)); return *this; } - + //!intersegment_ptr++. //!Never throws. intersegment_ptr operator++ (int) @@ -745,10 +745,10 @@ 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. + //!Not operator. Not needed in theory, but improves portability. //!Never throws. bool operator! () const { return base_t::is_null(); } @@ -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,74 +798,74 @@ 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 -bool operator!= (const intersegment_ptr<T1> &pt1, +bool operator!= (const intersegment_ptr<T1> &pt1, const intersegment_ptr<T2> &pt2) { return !(pt1 ==pt2); } //!intersegment_ptr<T1> <= intersegment_ptr<T2>. //!Never throws. template<class T1, class T2> inline -bool operator<= (const intersegment_ptr<T1> &pt1, +bool operator<= (const intersegment_ptr<T1> &pt1, const intersegment_ptr<T2> &pt2) { return !(pt1 > pt2); } //!intersegment_ptr<T1> > intersegment_ptr<T2>. //!Never throws. template<class T1, class T2> inline -bool operator> (const intersegment_ptr<T1> &pt1, +bool operator> (const intersegment_ptr<T1> &pt1, const intersegment_ptr<T2> &pt2) { return (pt2 < pt1); } //!intersegment_ptr<T1> >= intersegment_ptr<T2>. //!Never throws. template<class T1, class T2> inline -bool operator>= (const intersegment_ptr<T1> &pt1, +bool operator>= (const intersegment_ptr<T1> &pt1, const intersegment_ptr<T2> &pt2) { return !(pt1 < pt2); } //!operator<< template<class E, class T, class U> inline -std::basic_ostream<E, T> & operator<< +std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, const intersegment_ptr<U> & p) { return os << p.get(); } //!operator>> template<class E, class T, class U> inline -std::basic_istream<E, T> & operator>> +std::basic_istream<E, T> & operator>> (std::basic_istream<E, T> & os, intersegment_ptr<U> & p) { U * tmp; return os >> tmp; p = tmp; } -//!std::ptrdiff_t + intersegment_ptr. +//!std::ptrdiff_t + intersegment_ptr. //!The result is another pointer of the same segment template<class T> inline intersegment_ptr<T> operator+ (std::ptrdiff_t diff, const intersegment_ptr<T>& right) { return right + diff; } -//!intersegment_ptr - intersegment_ptr. +//!intersegment_ptr - intersegment_ptr. //!This only works with two intersegment_ptr-s that point to the //!same segment template <class T, class T2> inline -std::ptrdiff_t operator- (const intersegment_ptr<T> &pt, +std::ptrdiff_t operator- (const intersegment_ptr<T> &pt, const intersegment_ptr<T2> &pt2) { return pt._diff(pt2)/sizeof(T); } //! swap specialization template<class T> inline -void swap (boost::interprocess::intersegment_ptr<T> &pt, +void swap (boost::interprocess::intersegment_ptr<T> &pt, boost::interprocess::intersegment_ptr<T> &pt2) { pt.swap(pt2); } -//!to_raw_pointer() enables boost::mem_fn to recognize intersegment_ptr. +//!to_raw_pointer() enables boost::mem_fn to recognize intersegment_ptr. //!Never throws. template<class T> inline T * to_raw_pointer(boost::interprocess::intersegment_ptr<T> const & p) @@ -873,19 +873,19 @@ T * to_raw_pointer(boost::interprocess::intersegment_ptr<T> const & p) //!Simulation of static_cast between pointers. //!Never throws. -template<class T, class U> inline +template<class T, class U> inline boost::interprocess::intersegment_ptr<T> static_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r) { return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::static_cast_tag()); } //!Simulation of const_cast between pointers. //!Never throws. -template<class T, class U> inline +template<class T, class U> inline boost::interprocess::intersegment_ptr<T> const_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r) { return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::const_cast_tag()); } //!Simulation of dynamic_cast between pointers. //!Never throws. -template<class T, class U> inline +template<class T, class U> inline boost::interprocess::intersegment_ptr<T> dynamic_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r) { return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::dynamic_cast_tag()); } @@ -895,7 +895,7 @@ template<class T, class U> inline boost::interprocess::intersegment_ptr<T> reinterpret_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r) { return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::reinterpret_cast_tag()); } -//!Trait class to detect if an smart pointer has +//!Trait class to detect if an smart pointer has //!multi-segment addressing capabilities. template <class T> struct is_multisegment_ptr @@ -907,7 +907,7 @@ struct is_multisegment_ptr } //namespace interprocess { #if defined(_MSC_VER) && (_MSC_VER < 1400) -//!to_raw_pointer() enables boost::mem_fn to recognize intersegment_ptr. +//!to_raw_pointer() enables boost::mem_fn to recognize intersegment_ptr. //!Never throws. template<class T> inline T * to_raw_pointer(boost::interprocess::intersegment_ptr<T> const & p) @@ -918,14 +918,14 @@ T * to_raw_pointer(boost::interprocess::intersegment_ptr<T> const & p) //!for optimizations template <class T> struct has_trivial_constructor - < boost::interprocess::intersegment_ptr<T> > + < boost::interprocess::intersegment_ptr<T> > : public true_type{}; //!has_trivial_destructor<> == true_type specialization //!for optimizations template <class T> struct has_trivial_destructor - < boost::interprocess::intersegment_ptr<T> > + < boost::interprocess::intersegment_ptr<T> > : public true_type{}; } //namespace boost { @@ -950,7 +950,7 @@ struct has_trivial_destructor // std::size_t offset; //RELATIVE_SIZE_BITS = SIZE_T_BITS - -// MAX_SEGMENT_BITS - +// MAX_SEGMENT_BITS - // CTRL_BITS 10 10 //MAX_SEGMENT_SIZE = SIZE_T_BITS - ALIGN_BITS 20 52 diff --git a/boost/interprocess/detail/managed_global_memory.hpp b/boost/interprocess/detail/managed_global_memory.hpp new file mode 100644 index 0000000000..39dd0b1e6d --- /dev/null +++ b/boost/interprocess/detail/managed_global_memory.hpp @@ -0,0 +1,115 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP +#define BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP + +#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> + +#include <boost/interprocess/offset_ptr.hpp> +#include <boost/interprocess/sync/spin/mutex.hpp> +#include <boost/interprocess/sync/spin/recursive_mutex.hpp> +#include <boost/interprocess/detail/managed_memory_impl.hpp> +#include <boost/interprocess/detail/managed_open_or_create_impl.hpp> +#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> +#include <boost/interprocess/indexes/iset_index.hpp> +#include <boost/interprocess/creation_tags.hpp> +#include <boost/interprocess/permissions.hpp> + +namespace boost{ +namespace interprocess{ +namespace ipcdetail{ + +struct intermodule_singleton_mutex_family +{ + typedef boost::interprocess::ipcdetail::spin_mutex mutex_type; + typedef boost::interprocess::ipcdetail::spin_recursive_mutex recursive_mutex_type; +}; + +struct intermodule_types +{ + //We must use offset_ptr since a loaded DLL can map the singleton holder shared memory + //at a different address than other DLLs or the main executable + typedef rbtree_best_fit<intermodule_singleton_mutex_family, offset_ptr<void> > mem_algo; + template<class Device, bool FileBased> + struct open_or_create + { + typedef managed_open_or_create_impl + <Device, mem_algo::Alignment, FileBased> type; + }; +}; + +//we must implement our own managed shared memory to avoid circular dependencies +template<class Device, bool FileBased> +class basic_managed_global_memory + : public basic_managed_memory_impl + < char + , intermodule_types::mem_algo + , iset_index + , intermodule_types::open_or_create<Device, FileBased>::type::ManagedOpenOrCreateUserOffset + > + , private intermodule_types::open_or_create<Device, FileBased>::type +{ + /// @cond + typedef typename intermodule_types::template open_or_create<Device, FileBased>::type base2_t; + + typedef basic_managed_memory_impl + < char + , intermodule_types::mem_algo + , iset_index + , base2_t::ManagedOpenOrCreateUserOffset + > base_t; + + typedef create_open_func<base_t> create_open_func_t; + + basic_managed_global_memory *get_this_pointer() + { return this; } + + public: + typedef typename base_t::size_type size_type; + + private: + typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_global_memory) + /// @endcond + + public: //functions + + basic_managed_global_memory (open_or_create_t open_or_create, + const char *name, size_type size, + const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + DoOpenOrCreate), perm) + {} + + basic_managed_global_memory (open_only_t open_only, const char* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + DoOpen)) + {} +}; + + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //#ifndef BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP diff --git a/boost/interprocess/detail/managed_memory_impl.hpp b/boost/interprocess/detail/managed_memory_impl.hpp index 31c3804439..f9ecb8a860 100644 --- a/boost/interprocess/detail/managed_memory_impl.hpp +++ b/boost/interprocess/detail/managed_memory_impl.hpp @@ -34,7 +34,7 @@ #include <boost/assert.hpp> //!\file -//!Describes a named shared memory allocation user class. +//!Describes a named shared memory allocation user class. //! namespace boost { @@ -45,7 +45,7 @@ template<class BasicManagedMemoryImpl> class create_open_func; template< - class CharType, + class CharType, class MemoryAlgorithm, template<class IndexConfig> class IndexType > @@ -54,14 +54,14 @@ struct segment_manager_type typedef segment_manager<CharType, MemoryAlgorithm, IndexType> type; }; -//!This class is designed to be a base class to classes that manage -//!creation of objects in a fixed size memory buffer. Apart -//!from allocating raw memory, the user can construct named objects. To +//!This class is designed to be a base class to classes that manage +//!creation of objects in a fixed size memory buffer. Apart +//!from allocating raw memory, the user can construct named objects. To //!achieve this, this class uses the reserved space provided by the allocation //!algorithm to place a named_allocator_algo, who takes care of name mappings. //!The class can be customized with the char type used for object names //!and the memory allocation algorithm to be used.*/ -template < class CharType +template < class CharType , class MemoryAlgorithm , template<class IndexConfig> class IndexType , std::size_t Offset = 0 @@ -92,7 +92,7 @@ class basic_managed_memory_impl /// @cond - typedef typename + typedef typename segment_manager::char_ptr_holder_t char_ptr_holder_t; //Experimental. Don't use. @@ -153,7 +153,7 @@ class basic_managed_memory_impl } //!Constructor. Allocates basic resources. Never throws. - basic_managed_memory_impl() + basic_managed_memory_impl() : mp_header(0){} //!Destructor. Calls close. Never throws. @@ -169,19 +169,19 @@ class basic_managed_memory_impl if(size < segment_manager::get_min_size()) return false; - //This function should not throw. The index construction can + //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. bool open_impl (void *addr, size_type) { @@ -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; @@ -249,40 +249,40 @@ class basic_managed_memory_impl void zero_free_memory() { mp_header->zero_free_memory(); } - //!Transforms an absolute address into an offset from base address. + //!Transforms an absolute address into an offset from base address. //!The address must belong to the memory segment. Never throws. handle_t get_handle_from_address (const void *ptr) const { - return (handle_t)(reinterpret_cast<const char*>(ptr) - - reinterpret_cast<const char*>(this->get_address())); + return (handle_t)(reinterpret_cast<const char*>(ptr) - + reinterpret_cast<const char*>(this->get_address())); } //!Returns true if the address belongs to the managed memory segment bool belongs_to_segment (const void *ptr) const - { - return ptr >= this->get_address() && + { + return ptr >= this->get_address() && ptr < (reinterpret_cast<const char*>(this->get_address()) + this->get_size()); } - //!Transforms previously obtained offset into an absolute address in the + //!Transforms previously obtained offset into an absolute address in the //!process space of the current process. Never throws.*/ void * get_address_from_handle (handle_t offset) const { return reinterpret_cast<char*>(this->get_address()) + offset; } //!Searches for nbytes of free memory in the segment, marks the - //!memory as used and return the pointer to the memory. If no + //!memory as used and return the pointer to the memory. If no //!memory is available throws a boost::interprocess::bad_alloc exception void* allocate (size_type nbytes) { return mp_header->allocate(nbytes); } - //!Searches for nbytes of free memory in the segment, marks the - //!memory as used and return the pointer to the memory. If no memory + //!Searches for nbytes of free memory in the segment, marks the + //!memory as used and return the pointer to the memory. If no memory //!is available returns 0. Never throws. void* allocate (size_type nbytes, std::nothrow_t nothrow) { return mp_header->allocate(nbytes, nothrow); } //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment" - //!must be power of two. If no memory + //!must be power of two. If no memory //!is available returns 0. Never throws. void * allocate_aligned (size_type nbytes, size_type alignment, std::nothrow_t nothrow) { return mp_header->allocate_aligned(nbytes, alignment, nothrow); } @@ -292,13 +292,13 @@ 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); } //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment" - //!must be power of two. If no + //!must be power of two. If no //!memory is available throws a boost::interprocess::bad_alloc exception void * allocate_aligned(size_type nbytes, size_type alignment) { return mp_header->allocate_aligned(nbytes, alignment); } @@ -342,18 +342,18 @@ class basic_managed_memory_impl //!Creates a named object or array in memory //! - //!Allocates and constructs a T object or an array of T in memory, - //!associates this with the given name and returns a pointer to the + //!Allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the //!created object. If an array is being constructed all objects are //!created using the same parameters given to this function. //! //!-> If the name was previously used, returns 0. //! - //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //!-> Throws boost::interprocess::bad_alloc if there is no available memory //! //!-> If T's constructor throws, the function throws that exception. //! - //!Memory is freed automatically if T's constructor throws and if an + //!Memory is freed automatically if T's constructor throws and if an //!array was being constructed, destructors of created objects are called //!before freeing the memory. template <class T> @@ -363,18 +363,18 @@ class basic_managed_memory_impl //!Finds or creates a named object or array in memory //! - //!Tries to find an object with the given name in memory. If - //!found, returns the pointer to this pointer. If the object is not found, - //!allocates and constructs a T object or an array of T in memory, - //!associates this with the given name and returns a pointer to the + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the //!created object. If an array is being constructed all objects are //!created using the same parameters given to this function. //! - //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //!-> Throws boost::interprocess::bad_alloc if there is no available memory //! //!-> If T's constructor throws, the function throws that exception. //! - //!Memory is freed automatically if T's constructor throws and if an + //!Memory is freed automatically if T's constructor throws and if an //!array was being constructed, destructors of created objects are called //!before freeing the memory. template <class T> @@ -384,18 +384,18 @@ class basic_managed_memory_impl //!Creates a named object or array in memory //! - //!Allocates and constructs a T object or an array of T in memory, - //!associates this with the given name and returns a pointer to the + //!Allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the //!created object. If an array is being constructed all objects are //!created using the same parameters given to this function. //! //!-> If the name was previously used, returns 0. //! - //!-> Returns 0 if there is no available memory + //!-> Returns 0 if there is no available memory //! //!-> If T's constructor throws, the function throws that exception. //! - //!Memory is freed automatically if T's constructor throws and if an + //!Memory is freed automatically if T's constructor throws and if an //!array was being constructed, destructors of created objects are called //!before freeing the memory. template <class T> @@ -405,18 +405,18 @@ class basic_managed_memory_impl //!Finds or creates a named object or array in memory //! - //!Tries to find an object with the given name in memory. If - //!found, returns the pointer to this pointer. If the object is not found, - //!allocates and constructs a T object or an array of T in memory, - //!associates this with the given name and returns a pointer to the + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the //!created object. If an array is being constructed all objects are //!created using the same parameters given to this function. //! - //!-> Returns 0 if there is no available memory + //!-> Returns 0 if there is no available memory //! //!-> If T's constructor throws, the function throws that exception. //! - //!Memory is freed automatically if T's constructor throws and if an + //!Memory is freed automatically if T's constructor throws and if an //!array was being constructed, destructors of created objects are called //!before freeing the memory. template <class T> @@ -424,54 +424,54 @@ class basic_managed_memory_impl find_or_construct(char_ptr_holder_t name, std::nothrow_t nothrow) { return mp_header->template find_or_construct<T>(name, nothrow); } - //!Creates a named array from iterators in memory + //!Creates a named array from iterators in memory //! - //!Allocates and constructs an array of T in memory, - //!associates this with the given name and returns a pointer to the + //!Allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the //!created object. Each element in the array is created using the //!objects returned when dereferencing iterators as parameters //!and incrementing all iterators for each element. //! //!-> If the name was previously used, returns 0. //! - //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //!-> Throws boost::interprocess::bad_alloc if there is no available memory //! //!-> If T's constructor throws, the function throws that exception. //! - //!Memory is freed automatically if T's constructor throws and + //!Memory is freed automatically if T's constructor throws and //!destructors of created objects are called before freeing the memory. template <class T> typename segment_manager::template construct_iter_proxy<T>::type construct_it(char_ptr_holder_t name) { return mp_header->template construct_it<T>(name); } - //!Finds or creates a named array from iterators in memory + //!Finds or creates a named array from iterators in memory //! - //!Tries to find an object with the given name in memory. If - //!found, returns the pointer to this pointer. If the object is not found, - //!allocates and constructs an array of T in memory, - //!associates this with the given name and returns a pointer to the + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the //!created object. Each element in the array is created using the //!objects returned when dereferencing iterators as parameters //!and incrementing all iterators for each element. //! //!-> If the name was previously used, returns 0. //! - //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //!-> Throws boost::interprocess::bad_alloc if there is no available memory //! //!-> If T's constructor throws, the function throws that exception. //! - //!Memory is freed automatically if T's constructor throws and + //!Memory is freed automatically if T's constructor throws and //!destructors of created objects are called before freeing the memory. template <class T> typename segment_manager::template construct_iter_proxy<T>::type find_or_construct_it(char_ptr_holder_t name) { return mp_header->template find_or_construct_it<T>(name); } - //!Creates a named array from iterators in memory + //!Creates a named array from iterators in memory //! - //!Allocates and constructs an array of T in memory, - //!associates this with the given name and returns a pointer to the + //!Allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the //!created object. Each element in the array is created using the //!objects returned when dereferencing iterators as parameters //!and incrementing all iterators for each element. @@ -482,19 +482,19 @@ class basic_managed_memory_impl //! //!-> If T's constructor throws, the function throws that exception. //! - //!Memory is freed automatically if T's constructor throws and + //!Memory is freed automatically if T's constructor throws and //!destructors of created objects are called before freeing the memory.*/ template <class T> typename segment_manager::template construct_iter_proxy<T>::type construct_it(char_ptr_holder_t name, std::nothrow_t nothrow) { return mp_header->template construct_it<T>(name, nothrow); } - //!Finds or creates a named array from iterators in memory + //!Finds or creates a named array from iterators in memory //! - //!Tries to find an object with the given name in memory. If - //!found, returns the pointer to this pointer. If the object is not found, - //!allocates and constructs an array of T in memory, - //!associates this with the given name and returns a pointer to the + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the //!created object. Each element in the array is created using the //!objects returned when dereferencing iterators as parameters //!and incrementing all iterators for each element. @@ -505,7 +505,7 @@ class basic_managed_memory_impl //! //!-> If T's constructor throws, the function throws that exception. //! - //!Memory is freed automatically if T's constructor throws and + //!Memory is freed automatically if T's constructor throws and //!destructors of created objects are called before freeing the memory.*/ template <class T> typename segment_manager::template construct_iter_proxy<T>::type @@ -537,11 +537,11 @@ class basic_managed_memory_impl //! //!Exception Handling: //! - //!When deleting a dynamically object or array, the Standard + //!When deleting a dynamically object or array, the Standard //!does not guarantee that dynamically allocated memory, will be released. - //!Also, when deleting arrays, the Standard doesn't require calling - //!destructors for the rest of the objects if for one of them the destructor - //!terminated with an exception. + //!Also, when deleting arrays, the Standard doesn't require calling + //!destructors for the rest of the objects if for one of them the destructor + //!terminated with an exception. //! //!Destroying an object: //! @@ -550,13 +550,13 @@ class basic_managed_memory_impl //! //!Destroying an array: //! - //!When destroying an array, if a destructor throws, the rest of + //!When destroying an array, if a destructor throws, the rest of //!destructors are called. If any of these throws, the exceptions are //!ignored. The name association will be erased, memory will be freed and //!the first exception will be thrown. This guarantees the unlocking of //!mutexes and other resources. //! - //!For all theses reasons, classes with throwing destructors are not + //!For all theses reasons, classes with throwing destructors are not //!recommended. template <class T> bool destroy(const CharType *name) @@ -568,7 +568,7 @@ class basic_managed_memory_impl //! //!Exception Handling: //! - //!When deleting a dynamically object, the Standard does not + //!When deleting a dynamically object, the Standard does not //!guarantee that dynamically allocated memory will be released. //! //!Destroying an object: @@ -576,7 +576,7 @@ class basic_managed_memory_impl //!If the destructor throws, the memory will be freed and that exception //!will be thrown. //! - //!For all theses reasons, classes with throwing destructors are not + //!For all theses reasons, classes with throwing destructors are not //!recommended for memory. template <class T> bool destroy(const unique_instance_t *const ) @@ -588,7 +588,7 @@ class basic_managed_memory_impl //! //!Exception Handling: //! - //!When deleting a dynamically object, the Standard does not + //!When deleting a dynamically object, the Standard does not //!guarantee that dynamically allocated memory will be released. //! //!Destroying an object: @@ -596,7 +596,7 @@ class basic_managed_memory_impl //!If the destructor throws, the memory will be freed and that exception //!will be thrown. //! - //!For all theses reasons, classes with throwing destructors are not + //!For all theses reasons, classes with throwing destructors are not //!recommended for memory. template <class T> void destroy_ptr(const T *ptr) @@ -620,13 +620,13 @@ class basic_managed_memory_impl static size_type get_instance_length(const T *ptr) { return segment_manager::get_instance_length(ptr); } - //!Preallocates needed index resources to optimize the + //!Preallocates needed index resources to optimize the //!creation of "num" named objects in the memory segment. //!Can throw boost::interprocess::bad_alloc if there is no enough memory. void reserve_named_objects(size_type num) { mp_header->reserve_named_objects(num); } - //!Preallocates needed index resources to optimize the + //!Preallocates needed index resources to optimize the //!creation of "num" unique objects in the memory segment. //!Can throw boost::interprocess::bad_alloc if there is no enough memory. void reserve_unique_objects(size_type num) @@ -652,7 +652,7 @@ class basic_managed_memory_impl const_named_iterator named_begin() const { return mp_header->named_begin(); } - //!Returns a constant iterator to the end of the index + //!Returns a constant iterator to the end of the index //!storing the named allocations. NOT thread-safe. Never throws. const_named_iterator named_end() const { return mp_header->named_end(); } @@ -662,7 +662,7 @@ class basic_managed_memory_impl const_unique_iterator unique_begin() const { return mp_header->unique_begin(); } - //!Returns a constant iterator to the end of the index + //!Returns a constant iterator to the end of the index //!storing the unique allocations. NOT thread-safe. Never throws. const_unique_iterator unique_end() const { return mp_header->unique_end(); } @@ -724,8 +724,8 @@ class create_open_func : m_frontend(frontend), m_type(type){} bool operator()(void *addr, typename BasicManagedMemoryImpl::size_type size, bool created) const - { - if(((m_type == DoOpen) && created) || + { + if(((m_type == DoOpen) && created) || ((m_type == DoCreate) && !created)) return false; diff --git a/boost/interprocess/detail/managed_multi_shared_memory.hpp b/boost/interprocess/detail/managed_multi_shared_memory.hpp index 579d1ad6ff..654c8bb9f3 100644 --- a/boost/interprocess/detail/managed_multi_shared_memory.hpp +++ b/boost/interprocess/detail/managed_multi_shared_memory.hpp @@ -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 @@ -51,25 +51,25 @@ namespace interprocess { //-Use GetSecurityInfo? //-Change everything to use only a shared memory object expanded via truncate()? -//!A basic shared memory named object creation class. Initializes the -//!shared memory segment. Inherits all basic functionality from +//!A basic shared memory named object creation class. Initializes the +//!shared memory segment. Inherits all basic functionality from //!basic_managed_memory_impl<CharType, MemoryAlgorithm, IndexType> template < - class CharType, - class MemoryAlgorithm, + class CharType, + class MemoryAlgorithm, template<class IndexConfig> class IndexType > -class basic_managed_multi_shared_memory +class basic_managed_multi_shared_memory : public ipcdetail::basic_managed_memory_impl <CharType, MemoryAlgorithm, IndexType> { typedef basic_managed_multi_shared_memory <CharType, MemoryAlgorithm, IndexType> self_t; - typedef ipcdetail::basic_managed_memory_impl + 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; @@ -91,7 +91,7 @@ class basic_managed_multi_shared_memory // { // public: // segment_creator(shared_memory &shmem, -// const char *mem_name, +// const char *mem_name, // const void *addr) // : m_shmem(shmem), m_mem_name(mem_name), m_addr(addr){} // @@ -99,8 +99,8 @@ class basic_managed_multi_shared_memory // { // if(!m_shmem.create(m_mem_name, size, m_addr)) // return 0; -// return m_shmem.get_address(); -// } +// return m_shmem.get_address(); +// } // private: // shared_memory &m_shmem; // const char *m_mem_name; @@ -113,7 +113,7 @@ class basic_managed_multi_shared_memory public: typedef std::pair<void *, size_type> result_type; typedef basic_managed_multi_shared_memory frontend_t; - typedef typename + typedef typename basic_managed_multi_shared_memory::void_pointer void_pointer; typedef typename void_pointer::segment_group_id segment_group_id; group_services(frontend_t *const frontend) @@ -127,14 +127,14 @@ class basic_managed_multi_shared_memory alloc_size += 1; //If requested size is less than minimum, update that - alloc_size = (m_min_segment_size > alloc_size) ? + alloc_size = (m_min_segment_size > alloc_size) ? m_min_segment_size : alloc_size; if(mp_frontend->priv_new_segment(create_open_func::DoCreate, alloc_size, 0, permissions())){ typename shmem_list_t::value_type &m_impl = *mp_frontend->m_shmem_list.rbegin(); return result_type(m_impl.get_real_address(), m_impl.get_real_size()-1); }*/ - return result_type(static_cast<void *>(0), 0); + return result_type(static_cast<void *>(0), 0); } virtual bool update_segments () @@ -166,7 +166,7 @@ class basic_managed_multi_shared_memory struct create_open_func { enum type_t { DoCreate, DoOpen, DoOpenOrCreate }; - typedef typename + typedef typename basic_managed_multi_shared_memory::void_pointer void_pointer; create_open_func(self_t * const frontend, @@ -174,8 +174,8 @@ 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) || + { + if(((m_type == DoOpen) && created) || ((m_type == DoCreate) && !created)) return false; segment_group_id group = mp_frontend->m_group_services.get_group(); @@ -191,7 +191,7 @@ class basic_managed_multi_shared_memory //Check if this is the master segment if(!m_segment_number){ //Create or open the Interprocess machinery - if((impl_done = created ? + if((impl_done = created ? mp_frontend->create_impl(addr, size) : mp_frontend->open_impl(addr, size))){ return true; } @@ -219,14 +219,14 @@ class basic_managed_multi_shared_memory //!Functor to execute atomically when closing a shared memory segment. struct close_func { - typedef typename + typedef typename basic_managed_multi_shared_memory::void_pointer void_pointer; close_func(self_t * const frontend) : mp_frontend(frontend){} void operator()(const mapped_region ®ion, bool last) const - { + { if(last) mp_frontend->destroy_impl(); else mp_frontend->close_impl(); } @@ -251,7 +251,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, @@ -273,7 +273,7 @@ class basic_managed_multi_shared_memory { this->priv_close(); } private: - bool priv_open_or_create(typename create_open_func::type_t type, + bool priv_open_or_create(typename create_open_func::type_t type, const char *name, size_type size, const permissions &perm) @@ -301,7 +301,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, @@ -312,7 +312,7 @@ class basic_managed_multi_shared_memory BOOST_TRY{ //Get the number of groups of this multi_segment group size_type segment_id = m_shmem_list.size(); - //Format the name of the shared memory: append segment number. + //Format the name of the shared memory: append segment number. boost::interprocess::basic_ovectorstream<boost::interprocess::string> formatter; //Pre-reserve string size size_type str_size = m_root_name.length()+10; @@ -368,7 +368,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 +385,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 4d6997f330..a4f1f15817 100644 --- a/boost/interprocess/detail/managed_open_or_create_impl.hpp +++ b/boost/interprocess/detail/managed_open_or_create_impl.hpp @@ -48,12 +48,12 @@ class xsi_key; template<> struct managed_open_or_create_impl_device_id_t<xsi_shared_memory_file_wrapper> -{ +{ typedef xsi_key type; }; #endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS - + /// @endcond namespace ipcdetail { @@ -79,7 +79,7 @@ class managed_open_or_create_impl_device_holder<true, DeviceAbstraction> const DeviceAbstraction &get_device() const { return dev; } - + private: DeviceAbstraction dev; }; @@ -94,16 +94,16 @@ 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 }; public: static const std::size_t - ManagedOpenOrCreateUserOffset = + ManagedOpenOrCreateUserOffset = ct_rounded_size < sizeof(boost::uint32_t) , MemAlignment ? (MemAlignment) : @@ -113,7 +113,7 @@ class managed_open_or_create_impl managed_open_or_create_impl() {} - managed_open_or_create_impl(create_only_t, + managed_open_or_create_impl(create_only_t, const device_id_t & id, std::size_t size, mode_t mode, @@ -130,7 +130,7 @@ class managed_open_or_create_impl , null_mapped_region_function()); } - managed_open_or_create_impl(open_only_t, + managed_open_or_create_impl(open_only_t, const device_id_t & id, mode_t mode, const void *addr) @@ -146,7 +146,7 @@ class managed_open_or_create_impl } - managed_open_or_create_impl(open_or_create_t, + managed_open_or_create_impl(open_or_create_t, const device_id_t & id, std::size_t size, mode_t mode, @@ -164,7 +164,7 @@ class managed_open_or_create_impl } template <class ConstructFunc> - managed_open_or_create_impl(create_only_t, + managed_open_or_create_impl(create_only_t, const device_id_t & id, std::size_t size, mode_t mode, @@ -183,7 +183,7 @@ class managed_open_or_create_impl } template <class ConstructFunc> - managed_open_or_create_impl(open_only_t, + managed_open_or_create_impl(open_only_t, const device_id_t & id, mode_t mode, const void *addr, @@ -200,7 +200,7 @@ class managed_open_or_create_impl } template <class ConstructFunc> - managed_open_or_create_impl(open_or_create_t, + managed_open_or_create_impl(open_or_create_t, const device_id_t & id, std::size_t size, mode_t mode, @@ -222,10 +222,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() @@ -298,10 +298,10 @@ class managed_open_or_create_impl tmp.swap(dev); } - template <class ConstructFunc> inline + template <class ConstructFunc> inline void priv_open_or_create - (create_enum_t type, - const device_id_t & id, + (create_enum_t type, + const device_id_t & id, std::size_t size, mode_t mode, const void *addr, const permissions &perm, @@ -396,7 +396,8 @@ class managed_open_or_create_impl if(previous == UninitializedSegment){ try{ - construct_func(static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset, size - ManagedOpenOrCreateUserOffset, true); + construct_func( static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset + , size - ManagedOpenOrCreateUserOffset, true); //All ok, just move resources to the external mapped region m_mapped_region.swap(region); } diff --git a/boost/interprocess/detail/math_functions.hpp b/boost/interprocess/detail/math_functions.hpp index 08274160db..2fc457c683 100644 --- a/boost/interprocess/detail/math_functions.hpp +++ b/boost/interprocess/detail/math_functions.hpp @@ -4,7 +4,7 @@ // (C) Copyright Ion Gaztanaga 2007-2011. // // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at +// (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. @@ -93,7 +93,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 75aa00f87b..1f4ebdfc33 100644 --- a/boost/interprocess/detail/min_max.hpp +++ b/boost/interprocess/detail/min_max.hpp @@ -21,7 +21,7 @@ #include <boost/interprocess/detail/workaround.hpp> namespace boost { -namespace interprocess { +namespace interprocess { template<class T> const T &max_value(const T &a, const T &b) @@ -31,7 +31,7 @@ template<class T> const T &min_value(const T &a, const T &b) { return a < b ? a : b; } -} //namespace interprocess { +} //namespace interprocess { } //namespace boost { #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/detail/mpl.hpp b/boost/interprocess/detail/mpl.hpp index c5b6f90ef1..e2c7f52d24 100644 --- a/boost/interprocess/detail/mpl.hpp +++ b/boost/interprocess/detail/mpl.hpp @@ -20,7 +20,7 @@ #include <cstddef> namespace boost { -namespace interprocess { +namespace interprocess { namespace ipcdetail { template <class T, T val> @@ -105,24 +105,24 @@ struct if_ template <class Pair> -struct select1st -// : public std::unary_function<Pair, typename Pair::first_type> +struct select1st +// : public std::unary_function<Pair, typename Pair::first_type> { template<class OtherPair> - const typename Pair::first_type& operator()(const OtherPair& x) const + const typename Pair::first_type& operator()(const OtherPair& x) const { return x.first; } - const typename Pair::first_type& operator()(const typename Pair::first_type& x) const + const typename Pair::first_type& operator()(const typename Pair::first_type& x) const { return x; } }; // identity is an extension: it is not part of the standard. template <class T> -struct identity -// : public std::unary_function<T,T> +struct identity +// : public std::unary_function<T,T> { typedef T type; - const T& operator()(const T& x) const + const T& operator()(const T& x) const { return x; } }; @@ -144,8 +144,8 @@ struct ls_zeros<1> static const std::size_t value = 0; }; -} //namespace ipcdetail { -} //namespace interprocess { +} //namespace ipcdetail { +} //namespace interprocess { } //namespace boost { #endif //#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP diff --git a/boost/interprocess/detail/multi_segment_services.hpp b/boost/interprocess/detail/multi_segment_services.hpp index 4b6cafc742..d1451d3379 100644 --- a/boost/interprocess/detail/multi_segment_services.hpp +++ b/boost/interprocess/detail/multi_segment_services.hpp @@ -20,7 +20,7 @@ /*!\file - Describes a named shared memory allocation user class. + Describes a named shared memory allocation user class. */ namespace boost { diff --git a/boost/interprocess/detail/named_proxy.hpp b/boost/interprocess/detail/named_proxy.hpp index 604d7881ea..c2aafed9ac 100644 --- a/boost/interprocess/detail/named_proxy.hpp +++ b/boost/interprocess/detail/named_proxy.hpp @@ -24,7 +24,7 @@ #include <boost/interprocess/detail/mpl.hpp> #ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING -#include <boost/interprocess/detail/preprocessor.hpp> +#include <boost/interprocess/detail/preprocessor.hpp> #else #include <boost/move/move.hpp> #include <boost/interprocess/detail/variadic_templates_tools.hpp> @@ -34,7 +34,7 @@ //!Describes a proxy class that implements named allocation syntax. namespace boost { -namespace interprocess { +namespace interprocess { namespace ipcdetail { #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING @@ -83,7 +83,7 @@ struct CtorNArg : public placement_destroy<T> { this->expansion_helper(++get<IdxPack>(args_)...); } - + template<class ...ExpansionArgs> void expansion_helper(ExpansionArgs &&...) {} @@ -93,11 +93,11 @@ struct CtorNArg : public placement_destroy<T> {} tuple<Args&...> args_; -}; +}; //!Describes a proxy class that implements named //!allocation syntax. -template +template < class SegmentManager //segment manager to construct the object , class T //type of object to build , bool is_iterator //passing parameters are normal object or iterators? @@ -119,10 +119,10 @@ 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 + return mp_mngr->template generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj); } @@ -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); } // @@ -270,7 +270,7 @@ struct Ctor0Arg : public placement_destroy<T> //!Describes a proxy class that implements named //!allocation syntax. -template +template < class SegmentManager //segment manager to construct the object , class T //type of object to build , bool is_iterator //passing parameters are normal object or iterators? @@ -293,9 +293,9 @@ class named_proxy //!makes a named allocation and calls the //!default constructor T *operator()() const - { + { Ctor0Arg<T> ctor_obj; - return mp_mngr->template + return mp_mngr->template generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj); } //! @@ -322,7 +322,7 @@ class named_proxy //////////////////////////////////////////////////////////////////////// // // template <class P1, class P2> - // T *operator()(P1 &p1, P2 &p2) const + // T *operator()(P1 &p1, P2 &p2) const // { // typedef Ctor2Arg // <T, is_iterator, P1, P2> diff --git a/boost/interprocess/detail/os_file_functions.hpp b/boost/interprocess/detail/os_file_functions.hpp index b680c57132..08decd9bc4 100644 --- a/boost/interprocess/detail/os_file_functions.hpp +++ b/boost/interprocess/detail/os_file_functions.hpp @@ -32,7 +32,7 @@ # include <cstdio> # include <dirent.h> # if 0 -# include <sys/file.h> +# include <sys/file.h> # endif # else # error Unknown platform @@ -58,7 +58,7 @@ typedef enum { read_only = winapi::generic_read , read_write = winapi::generic_read | winapi::generic_write , copy_on_write , read_private - , invalid_mode = 0xffff + , invalid_mode = 0xffff } mode_t; typedef enum { file_begin = winapi::file_begin @@ -96,28 +96,28 @@ inline const char *get_temporary_path() 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) @@ -140,7 +140,7 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size) if(offset_t(size) > filesize){ if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){ return false; - } + } //We will write zeros in the end of the file //since set_end_of_file does not guarantee this for(std::size_t remaining = size - filesize, write_size = 0 @@ -177,7 +177,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 +189,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 = 0xffffffff; + const unsigned long len = ~((unsigned long)(0u)); // winapi::interprocess_overlapped overlapped; // std::memset(&overlapped, 0, sizeof(overlapped)); return winapi::lock_file_ex @@ -199,44 +199,44 @@ 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 = 0xffffffff; +{ + const unsigned long len = ~((unsigned long)(0u)); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); if(!winapi::lock_file_ex - (hnd, winapi::lockfile_exclusive_lock | winapi::lockfile_fail_immediately, + (hnd, winapi::lockfile_exclusive_lock | winapi::lockfile_fail_immediately, 0, len, len, &overlapped)){ - return winapi::get_last_error() == winapi::error_lock_violation ? + return winapi::get_last_error() == winapi::error_lock_violation ? acquired = false, true : false; - + } return (acquired = true); } inline bool release_file_lock(file_handle_t hnd) -{ - const unsigned long len = 0xffffffff; +{ + const unsigned long len = ~((unsigned long)(0u)); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped); } inline bool acquire_file_lock_sharable(file_handle_t hnd) -{ - const unsigned long len = 0xffffffff; +{ + const unsigned long len = ~((unsigned long)(0u)); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped); } inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) -{ - const unsigned long len = 0xffffffff; +{ + const unsigned long len = ~((unsigned long)(0u)); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); if(!winapi::lock_file_ex (hnd, winapi::lockfile_fail_immediately, 0, len, len, &overlapped)){ - return winapi::get_last_error() == winapi::error_lock_violation ? + return winapi::get_last_error() == winapi::error_lock_violation ? acquired = false, true : false; } return (acquired = true); @@ -367,7 +367,7 @@ typedef enum { read_only = O_RDONLY , read_write = O_RDWR , copy_on_write , read_private - , invalid_mode = 0xffff + , invalid_mode = 0xffff } mode_t; typedef enum { file_begin = SEEK_SET @@ -406,7 +406,7 @@ inline const char *get_temporary_path() 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){ @@ -439,7 +439,7 @@ inline file_handle_t create_or_open_file inline file_handle_t open_existing_file (const char *name, mode_t mode, bool temporary = false) -{ +{ (void)temporary; return ::open(name, (int)mode); } @@ -459,7 +459,7 @@ inline bool truncate_file (file_handle_t hnd, std::size_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 +472,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 +522,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 +532,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; @@ -540,7 +540,7 @@ inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) lock.l_len = 0; int ret = ::fcntl(hnd, F_SETLK, &lock); if(ret == -1){ - return (errno == EAGAIN || errno == EACCES) ? + return (errno == EAGAIN || errno == EACCES) ? acquired = false, true : false; } return (acquired = true); @@ -601,7 +601,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; diff --git a/boost/interprocess/detail/os_thread_functions.hpp b/boost/interprocess/detail/os_thread_functions.hpp index e49e82c8e0..8d769fc4e9 100644 --- a/boost/interprocess/detail/os_thread_functions.hpp +++ b/boost/interprocess/detail/os_thread_functions.hpp @@ -104,7 +104,7 @@ 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() {} @@ -153,7 +153,7 @@ inline OS_thread_id_t get_current_thread_id() { return ::pthread_self(); } inline OS_thread_id_t get_invalid_thread_id() -{ +{ static pthread_t invalid_id; return invalid_id; } diff --git a/boost/interprocess/detail/pointer_type.hpp b/boost/interprocess/detail/pointer_type.hpp index 7c45be085e..549b23fa6c 100644 --- a/boost/interprocess/detail/pointer_type.hpp +++ b/boost/interprocess/detail/pointer_type.hpp @@ -61,11 +61,11 @@ template <class T, class D> struct pointer_type { typedef typename pointer_type_imp::pointer_type<T, - typename ipcdetail::remove_reference<D>::type>::type type; + typename remove_reference<D>::type>::type type; }; } //namespace ipcdetail { -} //namespace interprocess { +} //namespace interprocess { } //namespace boost { #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/detail/portable_intermodule_singleton.hpp b/boost/interprocess/detail/portable_intermodule_singleton.hpp new file mode 100644 index 0000000000..eb2a13e104 --- /dev/null +++ b/boost/interprocess/detail/portable_intermodule_singleton.hpp @@ -0,0 +1,356 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP +#define BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP + +#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> + +#include <boost/interprocess/detail/managed_global_memory.hpp> +#include <boost/interprocess/detail/intermodule_singleton_common.hpp> +#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/os_file_functions.hpp> +#include <boost/interprocess/detail/file_locking_helpers.hpp> +#include <boost/assert.hpp> +#include <cstddef> +#include <cstdio> +#include <cstring> +#include <string> + +namespace boost{ +namespace interprocess{ +namespace ipcdetail{ + +typedef basic_managed_global_memory<shared_memory_object, true> managed_global_memory; + +namespace intermodule_singleton_helpers { + +static void create_tmp_subdir_and_get_pid_based_filepath + (const char *subdir_name, const char *file_prefix, OS_process_id_t pid, std::string &s, bool creation_time = false) +{ + //Let's create a lock file for each process gmem that will mark if + //the process is alive or not + create_tmp_and_clean_old(s); + s += "/"; + s += subdir_name; + if(!open_or_create_directory(s.c_str())){ + throw interprocess_exception(error_info(system_error_code())); + } + s += "/"; + s += file_prefix; + if(creation_time){ + std::string sstamp; + get_pid_creation_time_str(sstamp); + s += sstamp; + } + else{ + pid_str_t pid_str; + get_pid_str(pid_str, pid); + s += pid_str; + } +} + +static bool check_if_filename_complies_with_pid + (const char *filename, const char *prefix, OS_process_id_t pid, std::string &file_suffix, bool creation_time = false) +{ + //Check if filename complies with lock file name pattern + std::string fname(filename); + std::string fprefix(prefix); + if(fname.size() <= fprefix.size()){ + return false; + } + fname.resize(fprefix.size()); + if(fname != fprefix){ + return false; + } + + //If not our lock file, delete it if we can lock it + fname = filename; + fname.erase(0, fprefix.size()); + pid_str_t pid_str; + get_pid_str(pid_str, pid); + file_suffix = pid_str; + if(creation_time){ + std::size_t p = fname.find('_'); + if (p == std::string::npos){ + return false; + } + std::string save_suffix(fname); + fname.erase(p); + fname.swap(file_suffix); + bool ret = (file_suffix == fname); + file_suffix.swap(save_suffix); + return ret; + } + else{ + fname.swap(file_suffix); + return (file_suffix == fname); + } +} + +template<> +struct thread_safe_global_map_dependant<managed_global_memory> +{ + private: + static const int GMemMarkToBeRemoved = -1; + static const int GMemNotPresent = -2; + + static const char *get_lock_file_subdir_name() + { return "gmem"; } + + static const char *get_lock_file_base_name() + { return "lck"; } + + static void create_and_get_singleton_lock_file_path(std::string &s) + { + create_tmp_subdir_and_get_pid_based_filepath + (get_lock_file_subdir_name(), get_lock_file_base_name(), get_current_process_id(), s, true); + } + + struct gmem_erase_func + { + gmem_erase_func(const char *shm_name, const char *singleton_lock_file_path, managed_global_memory & shm) + :shm_name_(shm_name), singleton_lock_file_path_(singleton_lock_file_path), shm_(shm) + {} + + void operator()() + { + locking_file_serial_id *pserial_id = shm_.find<locking_file_serial_id>("lock_file_fd").first; + if(pserial_id){ + pserial_id->fd = GMemMarkToBeRemoved; + } + delete_file(singleton_lock_file_path_); + shared_memory_object::remove(shm_name_); + } + + const char * const shm_name_; + const char * const singleton_lock_file_path_; + managed_global_memory & shm_; + }; + + //This function applies shared memory erasure logic based on the passed lock file. + static void apply_gmem_erase_logic(const char *filepath, const char *filename) + { + int fd = GMemMarkToBeRemoved; + try{ + std::string str; + //If the filename is current process lock file, then avoid it + if(check_if_filename_complies_with_pid + (filename, get_lock_file_base_name(), get_current_process_id(), str, true)){ + return; + } + //Open and lock the other process' lock file + fd = try_open_and_lock_file(filepath); + if(fd < 0){ + return; + } + //If done, then the process is dead so take global shared memory name + //(the name is based on the lock file name) and try to apply erasure logic + str.insert(0, get_map_base_name()); + try{ + managed_global_memory shm(open_only, str.c_str()); + gmem_erase_func func(str.c_str(), filepath, shm); + shm.try_atomic_func(func); + } + catch(interprocess_exception &e){ + //If shared memory is not found erase the lock file + if(e.get_error_code() == not_found_error){ + delete_file(filepath); + } + } + } + catch(...){ + + } + if(fd >= 0){ + close_lock_file(fd); + } + } + + public: + + static bool remove_old_gmem() + { + std::string refcstrRootDirectory; + tmp_folder(refcstrRootDirectory); + refcstrRootDirectory += "/"; + refcstrRootDirectory += get_lock_file_subdir_name(); + return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic); + } + + struct lock_file_logic + { + lock_file_logic(managed_global_memory &shm) + : mshm(shm) + { shm.atomic_func(*this); } + + void operator()(void) + { + retry_with_new_map = false; + + //First find the file locking descriptor id + locking_file_serial_id *pserial_id = + mshm.find<locking_file_serial_id>("lock_file_fd").first; + + int fd; + //If not found schedule a creation + if(!pserial_id){ + fd = GMemNotPresent; + } + //Else get it + else{ + fd = pserial_id->fd; + } + //If we need to create a new one, do it + if(fd == GMemNotPresent){ + std::string lck_str; + //Create a unique current pid based lock file path + create_and_get_singleton_lock_file_path(lck_str); + //Open or create and lock file + int fd = open_or_create_and_lock_file(lck_str.c_str()); + //If failed, write a bad file descriptor to notify other modules that + //something was wrong and unlink shared memory. Mark the function object + //to tell caller to retry with another shared memory + if(fd < 0){ + this->register_lock_file(GMemMarkToBeRemoved); + std::string s; + get_map_name(s); + shared_memory_object::remove(s.c_str()); + retry_with_new_map = true; + } + //If successful, register the file descriptor + else{ + this->register_lock_file(fd); + } + } + //If the fd was invalid (maybe a previous try failed) notify caller that + //should retry creation logic, since this shm might have been already + //unlinked since the shm was removed + else if (fd == GMemMarkToBeRemoved){ + retry_with_new_map = true; + } + //If the stored fd is not valid (a open fd, a normal file with the + //expected size, or does not have the same file id number, + //then it's an old shm from an old process with the same pid. + //If that's the case, mark it as invalid + else if(!is_valid_fd(fd) || + !is_normal_file(fd) || + 0 != get_size(fd) || + !compare_file_serial(fd, *pserial_id)){ + pserial_id->fd = GMemMarkToBeRemoved; + std::string s; + get_map_name(s); + shared_memory_object::remove(s.c_str()); + retry_with_new_map = true; + } + else{ + //If the lock file is ok, increment reference count of + //attached modules to shared memory + atomic_inc32(&pserial_id->modules_attached_to_gmem_count); + } + } + + bool retry() const { return retry_with_new_map; } + + private: + locking_file_serial_id * register_lock_file(int fd) + { + locking_file_serial_id *pinfo = mshm.construct<locking_file_serial_id>("lock_file_fd")(); + fill_file_serial_id(fd, *pinfo); + return pinfo; + } + + managed_global_memory &mshm; + bool retry_with_new_map; + }; + + static void construct_map(void *addr) + { + std::string s; + intermodule_singleton_helpers::get_map_name(s); + const char *MapName = s.c_str(); + const std::size_t MapSize = intermodule_singleton_helpers::get_map_size();; + ::new (addr)managed_global_memory(open_or_create, MapName, MapSize); + } + + struct unlink_map_logic + { + unlink_map_logic(managed_global_memory &mshm) + : mshm_(mshm) + { mshm.atomic_func(*this); } + + void operator()() + { + locking_file_serial_id *pserial_id = + mshm_.find<locking_file_serial_id> + ("lock_file_fd").first; + BOOST_ASSERT(0 != pserial_id); + if(1 == atomic_dec32(&pserial_id->modules_attached_to_gmem_count)){ + int fd = pserial_id->fd; + if(fd > 0){ + pserial_id->fd = GMemMarkToBeRemoved; + std::string s; + create_and_get_singleton_lock_file_path(s); + delete_file(s.c_str()); + close_lock_file(fd); + intermodule_singleton_helpers::get_map_name(s); + shared_memory_object::remove(s.c_str()); + } + } + } + + private: + managed_global_memory &mshm_; + }; + + static ref_count_ptr *find(managed_global_memory &map, const char *name) + { + return map.find<ref_count_ptr>(name).first; + } + + static ref_count_ptr *insert(managed_global_memory &map, const char *name, const ref_count_ptr &ref) + { + return map.construct<ref_count_ptr>(name)(ref); + } + + static bool erase(managed_global_memory &map, const char *name) + { + return map.destroy<ref_count_ptr>(name); + } + + template<class F> + static void atomic_func(managed_global_memory &map, F &f) + { + map.atomic_func(f); + } +}; + +} //namespace intermodule_singleton_helpers { + +template<typename C, bool LazyInit = true, bool Phoenix = true> +class portable_intermodule_singleton + : public intermodule_singleton_impl<C, LazyInit, Phoenix, managed_global_memory> +{}; + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //#ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP diff --git a/boost/interprocess/detail/posix_time_types_wrk.hpp b/boost/interprocess/detail/posix_time_types_wrk.hpp index c1276f0f26..e4df85a572 100644 --- a/boost/interprocess/detail/posix_time_types_wrk.hpp +++ b/boost/interprocess/detail/posix_time_types_wrk.hpp @@ -15,7 +15,7 @@ #ifdef _WIN32 #ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN #define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN #endif //#ifndef WIN32_LEAN_AND_MEAN #endif //#ifdef _WIN32 diff --git a/boost/interprocess/detail/preprocessor.hpp b/boost/interprocess/detail/preprocessor.hpp index 4af2686452..47b591c901 100644 --- a/boost/interprocess/detail/preprocessor.hpp +++ b/boost/interprocess/detail/preprocessor.hpp @@ -21,7 +21,7 @@ #error "This file is not needed when perfect forwarding is available" #endif -#include <boost/preprocessor/iteration/local.hpp> +#include <boost/preprocessor/iteration/local.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/repetition/enum.hpp> @@ -57,28 +57,30 @@ #ifndef BOOST_NO_RVALUE_REFERENCES -#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES + #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_INTERPROCESS_MOVE_NAMESPACE::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \ -//! + #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \ + BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \ + //! -#else -#define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \ - BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \ -//! + #else //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) -#endif + #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) )) \ + //! -#else -#define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \ - BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \ -//! + #endif //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) + +#else //#ifndef BOOST_NO_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) \ + BOOST_PP_CAT(++m_p, n) \ //! #ifndef BOOST_NO_RVALUE_REFERENCES diff --git a/boost/interprocess/detail/ptime_wrk.hpp b/boost/interprocess/detail/ptime_wrk.hpp index 4a4709e3a8..8cda3a445d 100644 --- a/boost/interprocess/detail/ptime_wrk.hpp +++ b/boost/interprocess/detail/ptime_wrk.hpp @@ -15,7 +15,7 @@ #ifdef _WIN32 #ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN #define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN #endif //#ifndef WIN32_LEAN_AND_MEAN #endif //#ifdef _WIN32 diff --git a/boost/interprocess/detail/robust_emulation.hpp b/boost/interprocess/detail/robust_emulation.hpp index b2097d0ad7..1feb42dc35 100644 --- a/boost/interprocess/detail/robust_emulation.hpp +++ b/boost/interprocess/detail/robust_emulation.hpp @@ -68,7 +68,7 @@ inline void robust_lock_path(std::string &s) inline void create_and_get_robust_lock_file_path(std::string &s, OS_process_id_t pid) { - file_locking_helpers::create_tmp_subdir_and_get_pid_based_filepath + intermodule_singleton_helpers::create_tmp_subdir_and_get_pid_based_filepath (robust_lock_subdir_path(), robust_lock_prefix(), pid, s); } @@ -132,7 +132,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() { @@ -154,7 +154,7 @@ class robust_mutex_lock_file { std::string pid_str; //If the lock file is not our own lock file, then try to do the cleanup - if(!file_locking_helpers::check_if_filename_complies_with_pid + if(!intermodule_singleton_helpers::check_if_filename_complies_with_pid (filename, robust_lock_prefix(), get_current_process_id(), pid_str)){ remove_if_can_lock_file(filepath); } @@ -324,7 +324,7 @@ inline bool robust_spin_mutex<Mutex>::robust_check() return false; } atomic_write32(&this->state, fixing_state); - return true; + return true; } template<class Mutex> @@ -424,7 +424,7 @@ template<class Mutex> inline bool robust_spin_mutex<Mutex>::lock_own_unique_file() { //This function forces instantiation of the singleton - robust_emulation_helpers::robust_mutex_lock_file* dummy = + robust_emulation_helpers::robust_mutex_lock_file* dummy = &ipcdetail::intermodule_singleton <robust_emulation_helpers::robust_mutex_lock_file>::get(); return dummy != 0; diff --git a/boost/interprocess/detail/segment_manager_helper.hpp b/boost/interprocess/detail/segment_manager_helper.hpp index ea820b3881..2b715d8f5e 100644 --- a/boost/interprocess/detail/segment_manager_helper.hpp +++ b/boost/interprocess/detail/segment_manager_helper.hpp @@ -91,7 +91,7 @@ struct block_header , m_num_char((unsigned short)num_char) , m_value_alignment((unsigned char)value_alignment) , m_alloc_type_sizeof_char - ( (alloc_type << 5u) | + ( (alloc_type << 5u) | ((unsigned char)sizeof_char & 0x1F) ) {}; @@ -130,7 +130,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())); } @@ -139,7 +139,7 @@ struct block_header { return m_num_char; } size_type name_offset() const - { + { return this->value_offset() + get_rounded_size(size_type(m_value_bytes), size_type(sizeof_char())); } @@ -157,7 +157,7 @@ struct block_header bool less_comp(const block_header<size_type> &b) const { return m_num_char < b.m_num_char || - (m_num_char < b.m_num_char && + (m_num_char < b.m_num_char && std::char_traits<CharType>::compare (name<CharType>(), b.name<CharType>(), m_num_char) < 0); } @@ -175,10 +175,10 @@ 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 = + { + block_header * hdr = const_cast<block_header*> - (reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(value) - + (reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(value) - get_rounded_size(sizeof(block_header), algn))); (void)sz; //Some sanity checks @@ -189,9 +189,9 @@ 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) + + { + block_header<size_type> * hdr = + reinterpret_cast<block_header<size_type>*>(reinterpret_cast<char*>(header) + get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value))); //Some sanity checks return hdr; @@ -199,9 +199,9 @@ struct block_header template<class Header> static Header *to_first_header(block_header<size_type> *bheader) - { - Header * hdr = - reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) - + { + Header * hdr = + reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) - get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value))); //Some sanity checks return hdr; @@ -311,15 +311,15 @@ template<class CharType> class char_ptr_holder { public: - char_ptr_holder(const CharType *name) + char_ptr_holder(const CharType *name) : m_name(name) {} - char_ptr_holder(const anonymous_instance_t *) + char_ptr_holder(const anonymous_instance_t *) : m_name(static_cast<CharType*>(0)) {} - char_ptr_holder(const unique_instance_t *) + char_ptr_holder(const unique_instance_t *) : m_name(reinterpret_cast<CharType*>(-1)) {} @@ -330,7 +330,7 @@ class char_ptr_holder const CharType *m_name; }; -//!The key of the the named allocation information index. Stores an offset pointer +//!The key of the the named allocation information index. Stores an offset pointer //!to a null terminated string and the length of the string to speed up sorting template<class CharT, class VoidPointer> struct index_key @@ -356,9 +356,9 @@ struct index_key //!Less than function for index ordering bool operator < (const index_key & right) const { - return (m_len < right.m_len) || - (m_len == right.m_len && - std::char_traits<char_type>::compare + return (m_len < right.m_len) || + (m_len == right.m_len && + std::char_traits<char_type>::compare (to_raw_pointer(mp_str) ,to_raw_pointer(right.mp_str), m_len) < 0); } @@ -366,8 +366,8 @@ struct index_key //!Equal to function for index ordering bool operator == (const index_key & right) const { - return m_len == right.m_len && - std::char_traits<char_type>::compare + return m_len == right.m_len && + std::char_traits<char_type>::compare (to_raw_pointer(mp_str), to_raw_pointer(right.mp_str), m_len) == 0; } @@ -478,14 +478,14 @@ struct segment_manager_iterator_transform , segment_manager_iterator_value_adaptor<Iterator, intrusive> > { typedef segment_manager_iterator_value_adaptor<Iterator, intrusive> result_type; - + result_type operator()(const typename Iterator::value_type &arg) const { return result_type(arg); } }; } //namespace ipcdetail { -//These pointers are the ones the user will use to +//These pointers are the ones the user will use to //indicate previous allocation types static const ipcdetail::anonymous_instance_t * anonymous_instance = 0; static const ipcdetail::unique_instance_t * unique_instance = 0; diff --git a/boost/interprocess/detail/tmp_dir_helpers.hpp b/boost/interprocess/detail/tmp_dir_helpers.hpp index 38aafb2beb..28e7341406 100644 --- a/boost/interprocess/detail/tmp_dir_helpers.hpp +++ b/boost/interprocess/detail/tmp_dir_helpers.hpp @@ -18,80 +18,87 @@ #include <boost/interprocess/exceptions.hpp> #include <string> -#if defined(BOOST_INTERPROCESS_WINDOWS) - //#define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME - //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME - //#include <boost/interprocess/detail/win32_api.hpp> -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) - //#include <sys/sysctl.h> - //#if defined(CTL_KERN) && defined (KERN_BOOTTIME) - //#define BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME - //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME - //#endif +#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) && defined(BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/detail/windows_intermodule_singleton.hpp> #endif namespace boost { namespace interprocess { namespace ipcdetail { -#if defined (BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME) -inline void get_bootstamp(std::string &s, bool add = false) -{ - std::string bootstamp; - winapi::get_last_bootup_time(bootstamp); - if(add){ - s += bootstamp; - } - else{ - s.swap(bootstamp); - } -} -#elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME) -inline void get_bootstamp(std::string &s, bool add = false) -{ - // FreeBSD specific: sysctl "kern.boottime" - int request[2] = { CTL_KERN, KERN_BOOTTIME }; - struct ::timeval result; - std::size_t result_len = sizeof result; - - if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0) - return; - - char bootstamp_str[256]; - - const char Characters [] = - { '0', '1', '2', '3', '4', '5', '6', '7' - , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - - std::size_t char_counter = 0; - //32 bit values to allow 32 and 64 bit process IPC - boost::uint32_t fields[2] = { boost::uint32_t(result.tv_sec), boost::uint32_t(result.tv_usec) }; - for(std::size_t field = 0; field != 2; ++field){ - for(std::size_t i = 0; i != sizeof(fields[0]); ++i){ - const char *ptr = (const char *)&fields[field]; - bootstamp_str[char_counter++] = Characters[(ptr[i]&0xF0)>>4]; - bootstamp_str[char_counter++] = Characters[(ptr[i]&0x0F)]; +#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) + #if defined(BOOST_INTERPROCESS_WINDOWS) + //This type will initialize the stamp + struct windows_bootstamp + { + windows_bootstamp() + { + winapi::get_last_bootup_time(stamp); + } + //Use std::string. Even if this will be constructed in shared memory, all + //modules/dlls are from this process so internal raw pointers to heap are always valid + std::string stamp; + }; + + inline void get_bootstamp(std::string &s, bool add = false) + { + const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get(); + if(add){ + s += bootstamp.stamp; + } + else{ + s = bootstamp.stamp; + } } - } - bootstamp_str[char_counter] = 0; - if(add){ - s += bootstamp_str; - } - else{ - s = bootstamp_str; - } -} -#endif + #elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME) + inline void get_bootstamp(std::string &s, bool add = false) + { + // FreeBSD specific: sysctl "kern.boottime" + int request[2] = { CTL_KERN, KERN_BOOTTIME }; + struct ::timeval result; + std::size_t result_len = sizeof result; + + if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0) + return; + + char bootstamp_str[256]; + + const char Characters [] = + { '0', '1', '2', '3', '4', '5', '6', '7' + , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + std::size_t char_counter = 0; + //32 bit values to allow 32 and 64 bit process IPC + boost::uint32_t fields[2] = { boost::uint32_t(result.tv_sec), boost::uint32_t(result.tv_usec) }; + for(std::size_t field = 0; field != 2; ++field){ + for(std::size_t i = 0; i != sizeof(fields[0]); ++i){ + const char *ptr = (const char *)&fields[field]; + bootstamp_str[char_counter++] = Characters[(ptr[i]&0xF0)>>4]; + bootstamp_str[char_counter++] = Characters[(ptr[i]&0x0F)]; + } + } + bootstamp_str[char_counter] = 0; + if(add){ + s += bootstamp_str; + } + else{ + s = bootstamp_str; + } + } + #else + #error "BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME defined with no known implementation" + #endif +#endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) inline void get_tmp_base_dir(std::string &tmp_name) { #if defined (BOOST_INTERPROCESS_WINDOWS) - winapi::get_shared_documents_folder(tmp_name); - if(tmp_name.empty() || !winapi::is_directory(tmp_name.c_str())){ - tmp_name = get_temporary_path(); - } + winapi::get_shared_documents_folder(tmp_name); + if(tmp_name.empty() || !winapi::is_directory(tmp_name.c_str())){ + tmp_name = get_temporary_path(); + } #else - tmp_name = get_temporary_path(); + tmp_name = get_temporary_path(); #endif if(tmp_name.empty()){ error_info err = system_error_code(); @@ -104,9 +111,9 @@ inline void get_tmp_base_dir(std::string &tmp_name) inline void tmp_folder(std::string &tmp_name) { get_tmp_base_dir(tmp_name); - #ifdef BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME - tmp_name += "/"; - get_bootstamp(tmp_name, true); + #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) + tmp_name += "/"; + get_bootstamp(tmp_name, true); #endif } @@ -131,22 +138,22 @@ inline void create_tmp_and_clean_old(std::string &tmp_name) } } - #ifdef BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME - tmp_folder(tmp_name); + #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) + tmp_folder(tmp_name); - //If fails, check that it's because already exists - if(!create_directory(tmp_name.c_str())){ - error_info info(system_error_code()); - if(info.get_error_code() != already_exists_error){ - throw interprocess_exception(info); + //If fails, check that it's because already exists + if(!create_directory(tmp_name.c_str())){ + error_info info(system_error_code()); + if(info.get_error_code() != already_exists_error){ + throw interprocess_exception(info); + } } - } - //Now erase all old directories created in the previous boot sessions - std::string subdir = tmp_name; - subdir.erase(0, root_tmp_name.size()+1); - delete_subdirectories(root_tmp_name, subdir.c_str()); + //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; + tmp_name = root_tmp_name; #endif } diff --git a/boost/interprocess/detail/transform_iterator.hpp b/boost/interprocess/detail/transform_iterator.hpp index ef646fbefe..922c875d6d 100644 --- a/boost/interprocess/detail/transform_iterator.hpp +++ b/boost/interprocess/detail/transform_iterator.hpp @@ -27,7 +27,7 @@ #include <boost/interprocess/detail/type_traits.hpp> namespace boost { -namespace interprocess { +namespace interprocess { template <class PseudoReference> struct operator_arrow_proxy @@ -77,7 +77,7 @@ class transform_iterator {} //Constructors - transform_iterator& operator++() + transform_iterator& operator++() { increment(); return *this; } transform_iterator operator++(int) @@ -87,7 +87,7 @@ class transform_iterator return result; } - transform_iterator& operator--() + transform_iterator& operator--() { decrement(); return *this; } transform_iterator operator--(int) @@ -186,7 +186,7 @@ make_transform_iterator(Iterator it, UnaryFunc fun) return transform_iterator<Iterator, UnaryFunc>(it, fun); } -} //namespace interprocess { +} //namespace interprocess { } //namespace boost { #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/detail/type_traits.hpp b/boost/interprocess/detail/type_traits.hpp index 2cfa0be291..7a582fee5c 100644 --- a/boost/interprocess/detail/type_traits.hpp +++ b/boost/interprocess/detail/type_traits.hpp @@ -20,7 +20,7 @@ #include <boost/interprocess/detail/config_begin.hpp> namespace boost { -namespace interprocess { +namespace interprocess { namespace ipcdetail { struct nat{}; @@ -137,7 +137,7 @@ struct is_same }; } // namespace ipcdetail -} //namespace interprocess { +} //namespace interprocess { } //namespace boost { #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/detail/utilities.hpp b/boost/interprocess/detail/utilities.hpp index 625a9159d3..fcb211fb09 100644 --- a/boost/interprocess/detail/utilities.hpp +++ b/boost/interprocess/detail/utilities.hpp @@ -35,7 +35,7 @@ #include <algorithm> namespace boost { -namespace interprocess { +namespace interprocess { namespace ipcdetail { template <class T> @@ -138,9 +138,9 @@ template<class Cont> class value_eraser { public: - value_eraser(Cont & cont, typename Cont::iterator it) + 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; } @@ -151,7 +151,7 @@ class value_eraser bool m_erase; }; -} //namespace interprocess { +} //namespace interprocess { } //namespace boost { #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/detail/variadic_templates_tools.hpp b/boost/interprocess/detail/variadic_templates_tools.hpp index 1e6c4216e3..482a0056a7 100644 --- a/boost/interprocess/detail/variadic_templates_tools.hpp +++ b/boost/interprocess/detail/variadic_templates_tools.hpp @@ -21,7 +21,7 @@ #include <cstddef> //std::size_t namespace boost { -namespace interprocess { +namespace interprocess { namespace ipcdetail { template<typename... Values> @@ -136,7 +136,7 @@ struct index_tuple{}; template<std::size_t Num, typename Tuple = index_tuple<> > struct build_number_seq; -template<std::size_t Num, int... Indexes> +template<std::size_t Num, int... Indexes> struct build_number_seq<Num, index_tuple<Indexes...> > : build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> > {}; diff --git a/boost/interprocess/detail/win32_api.hpp b/boost/interprocess/detail/win32_api.hpp index b420c3d67b..c53725ca3b 100644 --- a/boost/interprocess/detail/win32_api.hpp +++ b/boost/interprocess/detail/win32_api.hpp @@ -46,6 +46,7 @@ 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; @@ -137,7 +138,14 @@ 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 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; @@ -159,7 +167,6 @@ 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; @@ -179,6 +186,27 @@ 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 { @@ -214,158 +242,158 @@ struct wchar_variant struct IUnknown_BIPC { public: - virtual long __stdcall QueryInterface( + virtual long __stdcall QueryInterface( /* [in] */ const GUID_BIPC &riid, /* [iid_is][out] */ void **ppvObject) = 0; - + virtual unsigned long __stdcall AddRef( void) = 0; - + virtual unsigned long __stdcall Release( void) = 0; }; struct IWbemClassObject_BIPC : public IUnknown_BIPC { public: - virtual long __stdcall GetQualifierSet( + virtual long __stdcall GetQualifierSet( /* [out] */ void **ppQualSet) = 0; - - virtual long __stdcall Get( + + virtual long __stdcall Get( /* [string][in] */ const wchar_t * wszName, /* [in] */ long lFlags, /* [unique][in][out] */ wchar_variant *pVal, /* [unique][in][out] */ long *pType, /* [unique][in][out] */ long *plFlavor) = 0; - - virtual long __stdcall Put( + + virtual long __stdcall Put( /* [string][in] */ const wchar_t * wszName, /* [in] */ long lFlags, /* [in] */ wchar_variant *pVal, /* [in] */ long Type) = 0; - - virtual long __stdcall Delete( + + virtual long __stdcall Delete( /* [string][in] */ const wchar_t * wszName) = 0; - - virtual long __stdcall GetNames( + + virtual long __stdcall GetNames( /* [string][in] */ const wchar_t * wszQualifierName, /* [in] */ long lFlags, /* [in] */ wchar_variant *pQualifierVal, /* [out] */ void * *pNames) = 0; - - virtual long __stdcall BeginEnumeration( + + virtual long __stdcall BeginEnumeration( /* [in] */ long lEnumFlags) = 0; - - virtual long __stdcall Next( + + virtual long __stdcall Next( /* [in] */ long lFlags, /* [unique][in][out] */ wchar_t * *strName, /* [unique][in][out] */ wchar_variant *pVal, /* [unique][in][out] */ long *pType, /* [unique][in][out] */ long *plFlavor) = 0; - + virtual long __stdcall EndEnumeration( void) = 0; - - virtual long __stdcall GetPropertyQualifierSet( + + virtual long __stdcall GetPropertyQualifierSet( /* [string][in] */ const wchar_t * wszProperty, /* [out] */ void **ppQualSet) = 0; - - virtual long __stdcall Clone( + + virtual long __stdcall Clone( /* [out] */ IWbemClassObject_BIPC **ppCopy) = 0; - - virtual long __stdcall GetObjectText( + + virtual long __stdcall GetObjectText( /* [in] */ long lFlags, /* [out] */ wchar_t * *pstrObjectText) = 0; - - virtual long __stdcall SpawnDerivedClass( + + virtual long __stdcall SpawnDerivedClass( /* [in] */ long lFlags, /* [out] */ IWbemClassObject_BIPC **ppNewClass) = 0; - - virtual long __stdcall SpawnInstance( + + virtual long __stdcall SpawnInstance( /* [in] */ long lFlags, /* [out] */ IWbemClassObject_BIPC **ppNewInstance) = 0; - - virtual long __stdcall CompareTo( + + virtual long __stdcall CompareTo( /* [in] */ long lFlags, /* [in] */ IWbemClassObject_BIPC *pCompareTo) = 0; - - virtual long __stdcall GetPropertyOrigin( + + virtual long __stdcall GetPropertyOrigin( /* [string][in] */ const wchar_t * wszName, /* [out] */ wchar_t * *pstrClassName) = 0; - - virtual long __stdcall InheritsFrom( + + virtual long __stdcall InheritsFrom( /* [in] */ const wchar_t * strAncestor) = 0; - - virtual long __stdcall GetMethod( + + virtual long __stdcall GetMethod( /* [string][in] */ const wchar_t * wszName, /* [in] */ long lFlags, /* [out] */ IWbemClassObject_BIPC **ppInSignature, /* [out] */ IWbemClassObject_BIPC **ppOutSignature) = 0; - - virtual long __stdcall PutMethod( + + virtual long __stdcall PutMethod( /* [string][in] */ const wchar_t * wszName, /* [in] */ long lFlags, /* [in] */ IWbemClassObject_BIPC *pInSignature, /* [in] */ IWbemClassObject_BIPC *pOutSignature) = 0; - - virtual long __stdcall DeleteMethod( + + virtual long __stdcall DeleteMethod( /* [string][in] */ const wchar_t * wszName) = 0; - - virtual long __stdcall BeginMethodEnumeration( + + virtual long __stdcall BeginMethodEnumeration( /* [in] */ long lEnumFlags) = 0; - - virtual long __stdcall NextMethod( + + virtual long __stdcall NextMethod( /* [in] */ long lFlags, /* [unique][in][out] */ wchar_t * *pstrName, /* [unique][in][out] */ IWbemClassObject_BIPC **ppInSignature, /* [unique][in][out] */ IWbemClassObject_BIPC **ppOutSignature) = 0; - + virtual long __stdcall EndMethodEnumeration( void) = 0; - - virtual long __stdcall GetMethodQualifierSet( + + virtual long __stdcall GetMethodQualifierSet( /* [string][in] */ const wchar_t * wszMethod, /* [out] */ void **ppQualSet) = 0; - - virtual long __stdcall GetMethodOrigin( + + virtual long __stdcall GetMethodOrigin( /* [string][in] */ const wchar_t * wszMethodName, /* [out] */ wchar_t * *pstrClassName) = 0; - + }; struct IWbemContext_BIPC : public IUnknown_BIPC { public: - virtual long __stdcall Clone( + virtual long __stdcall Clone( /* [out] */ IWbemContext_BIPC **ppNewCopy) = 0; - - virtual long __stdcall GetNames( + + virtual long __stdcall GetNames( /* [in] */ long lFlags, /* [out] */ void * *pNames) = 0; - - virtual long __stdcall BeginEnumeration( + + virtual long __stdcall BeginEnumeration( /* [in] */ long lFlags) = 0; - - virtual long __stdcall Next( + + virtual long __stdcall Next( /* [in] */ long lFlags, /* [out] */ wchar_t * *pstrName, /* [out] */ wchar_variant *pValue) = 0; - + virtual long __stdcall EndEnumeration( void) = 0; - - virtual long __stdcall SetValue( + + virtual long __stdcall SetValue( /* [string][in] */ const wchar_t * wszName, /* [in] */ long lFlags, /* [in] */ wchar_variant *pValue) = 0; - - virtual long __stdcall GetValue( + + virtual long __stdcall GetValue( /* [string][in] */ const wchar_t * wszName, /* [in] */ long lFlags, /* [out] */ wchar_variant *pValue) = 0; - - virtual long __stdcall DeleteValue( + + virtual long __stdcall DeleteValue( /* [string][in] */ const wchar_t * wszName, /* [in] */ long lFlags) = 0; - + virtual long __stdcall DeleteAll( void) = 0; - + }; @@ -373,157 +401,157 @@ struct IEnumWbemClassObject_BIPC : public IUnknown_BIPC { public: virtual long __stdcall Reset( void) = 0; - - virtual long __stdcall Next( + + virtual long __stdcall Next( /* [in] */ long lTimeout, /* [in] */ unsigned long uCount, /* [length_is][size_is][out] */ IWbemClassObject_BIPC **apObjects, /* [out] */ unsigned long *puReturned) = 0; - - virtual long __stdcall NextAsync( + + virtual long __stdcall NextAsync( /* [in] */ unsigned long uCount, /* [in] */ void *pSink) = 0; - - virtual long __stdcall Clone( + + virtual long __stdcall Clone( /* [out] */ void **ppEnum) = 0; - - virtual long __stdcall Skip( + + virtual long __stdcall Skip( /* [in] */ long lTimeout, /* [in] */ unsigned long nCount) = 0; - + }; struct IWbemServices_BIPC : public IUnknown_BIPC { public: - virtual long __stdcall OpenNamespace( + virtual long __stdcall OpenNamespace( /* [in] */ const wchar_t * strNamespace, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppWorkingNamespace, /* [unique][in][out] */ void **ppResult) = 0; - - virtual long __stdcall CancelAsyncCall( + + virtual long __stdcall CancelAsyncCall( /* [in] */ void *pSink) = 0; - - virtual long __stdcall QueryObjectSink( + + virtual long __stdcall QueryObjectSink( /* [in] */ long lFlags, /* [out] */ void **ppResponseHandler) = 0; - - virtual long __stdcall GetObject( + + virtual long __stdcall GetObject( /* [in] */ const wchar_t * strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppObject, /* [unique][in][out] */ void **ppCallResult) = 0; - - virtual long __stdcall GetObjectAsync( + + virtual long __stdcall GetObjectAsync( /* [in] */ const wchar_t * strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; - - virtual long __stdcall PutClass( + + virtual long __stdcall PutClass( /* [in] */ IWbemClassObject_BIPC *pObject, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppCallResult) = 0; - - virtual long __stdcall PutClassAsync( + + virtual long __stdcall PutClassAsync( /* [in] */ IWbemClassObject_BIPC *pObject, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; - - virtual long __stdcall DeleteClass( + + virtual long __stdcall DeleteClass( /* [in] */ const wchar_t * strClass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppCallResult) = 0; - - virtual long __stdcall DeleteClassAsync( + + virtual long __stdcall DeleteClassAsync( /* [in] */ const wchar_t * strClass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; - - virtual long __stdcall CreateClassEnum( + + virtual long __stdcall CreateClassEnum( /* [in] */ const wchar_t * strSuperclass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [out] */ void **ppEnum) = 0; - - virtual long __stdcall CreateClassEnumAsync( + + virtual long __stdcall CreateClassEnumAsync( /* [in] */ const wchar_t * strSuperclass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; - - virtual long __stdcall PutInstance( + + virtual long __stdcall PutInstance( /* [in] */ void *pInst, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppCallResult) = 0; - - virtual long __stdcall PutInstanceAsync( + + virtual long __stdcall PutInstanceAsync( /* [in] */ void *pInst, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; - - virtual long __stdcall DeleteInstance( + + virtual long __stdcall DeleteInstance( /* [in] */ const wchar_t * strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppCallResult) = 0; - - virtual long __stdcall DeleteInstanceAsync( + + virtual long __stdcall DeleteInstanceAsync( /* [in] */ const wchar_t * strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; - - virtual long __stdcall CreateInstanceEnum( + + virtual long __stdcall CreateInstanceEnum( /* [in] */ const wchar_t * strFilter, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [out] */ void **ppEnum) = 0; - - virtual long __stdcall CreateInstanceEnumAsync( + + virtual long __stdcall CreateInstanceEnumAsync( /* [in] */ const wchar_t * strFilter, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; - - virtual long __stdcall ExecQuery( + + virtual long __stdcall ExecQuery( /* [in] */ const wchar_t * strQueryLanguage, /* [in] */ const wchar_t * strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [out] */ IEnumWbemClassObject_BIPC **ppEnum) = 0; - virtual long __stdcall ExecQueryAsync( + virtual long __stdcall ExecQueryAsync( /* [in] */ const wchar_t * strQueryLanguage, /* [in] */ const wchar_t * strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [in] */ void *pResponseHandler) = 0; - - virtual long __stdcall ExecNotificationQuery( + + virtual long __stdcall ExecNotificationQuery( /* [in] */ const wchar_t * strQueryLanguage, /* [in] */ const wchar_t * strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [out] */ void **ppEnum) = 0; - - virtual long __stdcall ExecNotificationQueryAsync( + + virtual long __stdcall ExecNotificationQueryAsync( /* [in] */ const wchar_t * strQueryLanguage, /* [in] */ const wchar_t * strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [in] */ void *pResponseHandler) = 0; - - virtual long __stdcall ExecMethod( + + virtual long __stdcall ExecMethod( /* [in] */ const wchar_t * strObjectPath, /* [in] */ const wchar_t * strMethodName, /* [in] */ long lFlags, @@ -531,21 +559,21 @@ public: /* [in] */ IWbemClassObject_BIPC *pInParams, /* [unique][in][out] */ IWbemClassObject_BIPC **ppOutParams, /* [unique][in][out] */ void **ppCallResult) = 0; - - virtual long __stdcall ExecMethodAsync( + + virtual long __stdcall ExecMethodAsync( /* [in] */ const wchar_t * strObjectPath, /* [in] */ const wchar_t * strMethodName, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [in] */ IWbemClassObject_BIPC *pInParams, /* [in] */ void *pResponseHandler) = 0; - + }; struct IWbemLocator_BIPC : public IUnknown_BIPC { public: - virtual long __stdcall ConnectServer( + virtual long __stdcall ConnectServer( /* [in] */ const wchar_t * strNetworkResource, /* [in] */ const wchar_t * strUser, /* [in] */ const wchar_t * strPassword, @@ -554,12 +582,12 @@ public: /* [in] */ const wchar_t * strAuthority, /* [in] */ void *pCtx, /* [out] */ IWbemServices_BIPC **ppNamespace) = 0; - + }; - -struct interprocess_overlapped + +struct interprocess_overlapped { unsigned long *internal; unsigned long *internal_high; @@ -574,9 +602,22 @@ 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 -{ - unsigned long dwLowDateTime; +{ + unsigned long dwLowDateTime; unsigned long dwHighDateTime; }; @@ -620,16 +661,16 @@ struct system_info { unsigned short wProcessorRevision; }; -struct interprocess_memory_basic_information +typedef struct _interprocess_memory_basic_information { - void * BaseAddress; + 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 { @@ -695,6 +736,10 @@ enum file_information_class_t { file_maximum_information }; +enum semaphore_information_class { + semaphore_basic_information = 0 +}; + struct file_name_information_t { unsigned long FileNameLength; wchar_t FileName[1]; @@ -779,6 +824,12 @@ enum object_information_class object_data_information }; +enum section_information_class +{ + section_basic_information, + section_image_information +}; + struct object_name_information_t { unicode_string_t Name; @@ -803,6 +854,7 @@ extern "C" __declspec(dllimport) int __stdcall DuplicateHandle , void *hTargetProcessHandle, void **lpTargetHandle , unsigned long dwDesiredAccess, int bInheritHandle , unsigned long dwOptions); +extern "C" __declspec(dllimport) long __stdcall GetFileType(void *hFile); extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data_t *lpFindFileData); extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data_t *lpFindFileData); extern "C" __declspec(dllimport) int __stdcall FindClose(void *hFindFile); @@ -827,8 +879,8 @@ extern "C" __declspec(dllimport) int __stdcall FlushViewOfFile (void *, std::siz extern "C" __declspec(dllimport) int __stdcall FlushFileBuffers (void *); extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, __int64 *size); extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA - (unsigned long dwFlags, const void *lpSource, unsigned long dwMessageId, - unsigned long dwLanguageId, char *lpBuffer, unsigned long nSize, + (unsigned long dwFlags, const void *lpSource, unsigned long dwMessageId, + unsigned long dwLanguageId, char *lpBuffer, unsigned long nSize, std::va_list *Arguments); extern "C" __declspec(dllimport) void *__stdcall LocalFree (void *); extern "C" __declspec(dllimport) unsigned long __stdcall GetFileAttributesA(const char *); @@ -844,6 +896,7 @@ extern "C" __declspec(dllimport) int __stdcall UnlockFile(void *hnd, unsigned lo extern "C" __declspec(dllimport) int __stdcall LockFileEx(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped); extern "C" __declspec(dllimport) int __stdcall UnlockFileEx(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped); extern "C" __declspec(dllimport) int __stdcall WriteFile(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped); +extern "C" __declspec(dllimport) int __stdcall ReadFile(void *hnd, void *buffer, unsigned long bytes_to_read, unsigned long *bytes_read, interprocess_overlapped* overlapped); extern "C" __declspec(dllimport) int __stdcall InitializeSecurityDescriptor(interprocess_security_descriptor *pSecurityDescriptor, unsigned long dwRevision); extern "C" __declspec(dllimport) int __stdcall SetSecurityDescriptorDacl(interprocess_security_descriptor *pSecurityDescriptor, int bDaclPresent, interprocess_acl *pDacl, int bDaclDefaulted); extern "C" __declspec(dllimport) void *__stdcall LoadLibraryA(const char *); @@ -858,17 +911,17 @@ extern "C" __declspec(dllimport) long __stdcall RegCloseKey(void *); extern "C" __declspec(dllimport) int __stdcall QueryPerformanceCounter(__int64 *lpPerformanceCount); //COM API -extern "C" __declspec(dllimport) long __stdcall CoInitialize(void *pvReserved); +extern "C" __declspec(dllimport) long __stdcall CoInitializeEx(void *pvReserved, unsigned long dwCoInit); extern "C" __declspec(dllimport) long __stdcall CoInitializeSecurity( - void* pSecDesc, - long cAuthSvc, - void *asAuthSvc, - void *pReserved1, - unsigned long dwAuthnLevel, - unsigned long dwImpLevel, - void *pAuthList, - unsigned long dwCapabilities, - void *pReserved3 ); + void* pSecDesc, + long cAuthSvc, + void * asAuthSvc, + void *pReserved1, + unsigned long dwAuthnLevel, + unsigned long dwImpLevel, + void *pAuthList, + unsigned long dwCapabilities, + void *pReserved3 ); extern "C" __declspec(dllimport) long __stdcall CoSetProxyBlanket( IUnknown_BIPC *pProxy, @@ -889,10 +942,12 @@ extern "C" __declspec(dllimport) void __stdcall CoUninitialize(void); //API function typedefs //Pointer to functions -typedef long (__stdcall *NtDeleteFile_t)(object_attributes_t *ObjectAttributes); -typedef long (__stdcall *NtSetInformationFile_t)(void *FileHandle, io_status_block_t *IoStatusBlock, void *FileInformation, unsigned long Length, int FileInformationClass ); -typedef long (__stdcall * NtQuerySystemInformation_t)(int, void*, unsigned long, unsigned long *); -typedef long (__stdcall * NtQueryObject_t)(void*, object_information_class, void *, unsigned long, unsigned long *); +typedef long (__stdcall *NtDeleteFile_t)(object_attributes_t *ObjectAttributes); +typedef long (__stdcall *NtSetInformationFile_t)(void *FileHandle, io_status_block_t *IoStatusBlock, void *FileInformation, unsigned long Length, int FileInformationClass ); +typedef long (__stdcall *NtQuerySystemInformation_t)(int, void*, unsigned long, unsigned long *); +typedef long (__stdcall *NtQueryObject_t)(void*, object_information_class, void *, unsigned long, unsigned long *); +typedef long (__stdcall *NtQuerySemaphore_t)(void*, unsigned int info_class, interprocess_semaphore_basic_information *pinfo, unsigned int info_size, unsigned int *ret_len); +typedef long (__stdcall *NtQuerySection_t)(void*, section_information_class, interprocess_section_basic_information *pinfo, unsigned long info_size, unsigned long *ret_len); 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*); @@ -977,6 +1032,12 @@ inline bool duplicate_current_process_handle , lpTargetHandle, 0, 0 , duplicate_same_access); } + +inline long get_file_type(void *hFile) +{ + return GetFileType(hFile); +} + /* inline void get_system_time_as_file_time(interprocess_filetime *filetime) { GetSystemTimeAsFileTime(filetime); } @@ -1000,13 +1061,16 @@ inline int unmap_view_of_file(void *address) inline void *open_or_create_semaphore(const char *name, long initial_count, long maximum_count, interprocess_security_attributes *attr) { return CreateSemaphoreA(attr, initial_count, maximum_count, name); } +inline void *open_semaphore(const char *name) +{ return OpenSemaphoreA(semaphore_all_access, 0, name); } + inline int release_semaphore(void *handle, long release_count, long *prev_count) { return ReleaseSemaphore(handle, release_count, prev_count); } class interprocess_all_access_security { interprocess_security_attributes sa; - interprocess_security_descriptor sd; + interprocess_security_descriptor sd; bool initialized; public: @@ -1027,16 +1091,21 @@ class interprocess_all_access_security { return &sa; } }; -inline void * create_file_mapping (void * handle, unsigned long access, unsigned long high_size, unsigned long low_size, const char * name, interprocess_security_attributes *psec) +inline void * create_file_mapping (void * handle, unsigned long access, unsigned __int64 file_offset, const char * name, interprocess_security_attributes *psec) { - return CreateFileMappingA (handle, psec, access, high_size, low_size, name); + const unsigned long high_size(file_offset >> 32), low_size((boost::uint32_t)file_offset); + return CreateFileMappingA (handle, psec, access, high_size, low_size, name); } inline void * open_file_mapping (unsigned long access, const char *name) { return OpenFileMappingA (access, 0, name); } -inline void *map_view_of_file_ex(void *handle, unsigned long file_access, unsigned long highoffset, unsigned long lowoffset, std::size_t numbytes, void *base_addr) -{ return MapViewOfFileEx(handle, file_access, highoffset, lowoffset, numbytes, base_addr); } +inline void *map_view_of_file_ex(void *handle, unsigned long file_access, unsigned __int64 offset, std::size_t numbytes, void *base_addr) +{ + const unsigned long offset_low = (unsigned long)(offset & ((unsigned __int64)0xFFFFFFFF)); + const unsigned long offset_high = offset >> 32; + return MapViewOfFileEx(handle, file_access, offset_high, offset_low, numbytes, base_addr); +} inline void *create_file(const char *name, unsigned long access, unsigned long creation_flags, unsigned long attributes, interprocess_security_attributes *psec) { @@ -1051,7 +1120,7 @@ inline void *create_file(const char *name, unsigned long access, unsigned long c if (error_sharing_violation != get_last_error()){ return handle; } - Sleep(error_sharing_violation_sleep_ms); + sleep(error_sharing_violation_sleep_ms); } return invalid_handle_value; } @@ -1075,9 +1144,9 @@ inline bool get_file_size(void *handle, __int64 &size) { return 0 != GetFileSizeEx(handle, &size); } inline bool create_directory(const char *name) -{ +{ interprocess_all_access_security sec; - return 0 != CreateDirectoryA(name, sec.get_attributes()); + return 0 != CreateDirectoryA(name, sec.get_attributes()); } inline bool remove_directory(const char *lpPathName) @@ -1101,6 +1170,9 @@ inline bool unlock_file_ex(void *hnd, unsigned long reserved, unsigned long size inline bool write_file(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped) { return 0 != WriteFile(hnd, buffer, bytes_to_write, bytes_written, overlapped); } +inline bool read_file(void *hnd, void *buffer, unsigned long bytes_to_read, unsigned long *bytes_read, interprocess_overlapped* overlapped) +{ return 0 != ReadFile(hnd, buffer, bytes_to_read, bytes_read, overlapped); } + inline bool get_file_information_by_handle(void *hnd, interprocess_by_handle_file_information *info) { return 0 != GetFileInformationByHandle(hnd, info); } @@ -1176,7 +1248,7 @@ 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, NumFunction }; + enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NtQuerySemaphore, NtQuerySection, NumFunction }; enum { NtDll_dll, NumModule }; private: @@ -1213,7 +1285,7 @@ struct function_address_holder static void *get_address_from_dll(const unsigned int id) { assert(id < (unsigned int)NumFunction); - const char *function[] = { "NtSetInformationFile", "NtQuerySystemInformation", "NtQueryObject" }; + 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]); @@ -1264,7 +1336,7 @@ struct library_unloader //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) + (void * hFile, wchar_t *pszFilename, std::size_t length, std::size_t &out_length) { if(length <= MaxPath){ return false; @@ -1285,17 +1357,17 @@ inline bool get_file_name_from_handle_function bool bSuccess = false; // Create a file mapping object. - void * hFileMap = create_file_mapping(hFile, page_readonly, 0, 1, 0, 0); + 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, 0, 1, 0); + 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); @@ -1307,7 +1379,6 @@ inline bool get_file_name_from_handle_function inline bool get_system_time_of_day_information(system_timeofday_information &info) { NtQuerySystemInformation_t pNtQuerySystemInformation = (NtQuerySystemInformation_t) - //get_proc_address(get_module_handle("ntdll.dll"), "NtQuerySystemInformation"); dll_func::get(dll_func::NtQuerySystemInformation); unsigned long res; long status = pNtQuerySystemInformation(system_time_of_day_information, &info, sizeof(info), &res); @@ -1384,9 +1455,12 @@ inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t class handle_closer { void *handle_; + handle_closer(const handle_closer &); + handle_closer& operator=(const handle_closer &); public: - handle_closer(void *handle) : handle_(handle){} - ~handle_closer(){ close_handle(handle_); } + explicit handle_closer(void *handle) : handle_(handle){} + ~handle_closer() + { close_handle(handle_); } }; union ntquery_mem_t @@ -1401,81 +1475,92 @@ union ntquery_mem_t inline bool unlink_file(const char *filename) { - if(!delete_file(filename)){ - try{ - NtSetInformationFile_t pNtSetInformationFile = - //(NtSetInformationFile_t)get_proc_address(get_module_handle("ntdll.dll"), "NtSetInformationFile"); - (NtSetInformationFile_t)dll_func::get(dll_func::NtSetInformationFile); - if(!pNtSetInformationFile){ - return false; - } + //Don't try to optimize doing a DeleteFile first + //as there are interactions with permissions and + //in-use files. + // + //if(!delete_file(filename)){ + // (...) + // + + //This functions tries to emulate UNIX unlink semantics in windows. + // + //- Open the file and mark the handle as delete-on-close + //- Rename the file to an arbitrary name based on a random number + //- Close the handle. If there are no file users, it will be deleted. + // Otherwise it will be used by already connected handles but the + // file name can't be used to open this file again + try{ + NtSetInformationFile_t pNtSetInformationFile = + (NtSetInformationFile_t)dll_func::get(dll_func::NtSetInformationFile); + if(!pNtSetInformationFile){ + return false; + } - NtQueryObject_t pNtQueryObject = - //(NtQueryObject_t)get_proc_address(get_module_handle("ntdll.dll"), "NtQueryObject"); - (NtQueryObject_t)dll_func::get(dll_func::NtQueryObject); + 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); - if(fh == invalid_handle_value){ - return false; - } + //First step: Obtain a handle to the file using Win32 rules. This resolves relative paths + void *fh = create_file(filename, generic_read | delete_access, open_existing, + file_flag_backup_semantics | file_flag_delete_on_close, 0); + if(fh == invalid_handle_value){ + return false; + } - handle_closer h_closer(fh); + handle_closer h_closer(fh); - std::auto_ptr<ntquery_mem_t> pmem(new ntquery_mem_t); - file_rename_information_t *pfri = &pmem->ren.info; - const std::size_t RenMaxNumChars = - ((char*)pmem.get() - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t); + 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; - } + //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); + //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; - //} + //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; - } + //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; - } + //Search '\\' character to replace it + for(std::size_t i = filename_string_length; i != 0; --filename_string_length){ + if(pmem->ren.info.FileName[--i] == L'\\') + break; + } - //Add random number - std::size_t s = RenMaxNumChars - filename_string_length; - if(!get_boot_and_system_time_wstr(&pfri->FileName[filename_string_length], s)){ - return false; - } - filename_string_length += s; + //Add random number + std::size_t s = RenMaxNumChars - filename_string_length; + if(!get_boot_and_system_time_wstr(&pfri->FileName[filename_string_length], s)){ + return false; + } + filename_string_length += s; - //Fill rename information (FileNameLength is in bytes) - pfri->FileNameLength = static_cast<unsigned long>(sizeof(wchar_t)*(filename_string_length)); - pfri->Replace = 1; - pfri->RootDir = 0; + //Fill rename information (FileNameLength is in bytes) + pfri->FileNameLength = static_cast<unsigned long>(sizeof(wchar_t)*(filename_string_length)); + pfri->Replace = 1; + pfri->RootDir = 0; - //Final step: change the name of the in-use file: - io_status_block_t io; - if(0 != pNtSetInformationFile(fh, &io, pfri, sizeof(ntquery_mem_t::ren_t), file_rename_information)){ - return false; - } - return true; - } - catch(...){ + //Final step: change the name of the in-use file: + io_status_block_t io; + if(0 != pNtSetInformationFile(fh, &io, pfri, sizeof(ntquery_mem_t::ren_t), file_rename_information)){ return false; } + return true; + } + catch(...){ + return false; } return true; } @@ -1493,116 +1578,77 @@ struct reg_closer inline void get_shared_documents_folder(std::string &s) { s.clear(); - //void *hAdvapi = load_library("Advapi32.dll"); - //if (hAdvapi){ - //library_unloader unloader(hAdvapi); - // Pointer to function RegOpenKeyA - //RegOpenKeyEx_t pRegOpenKey = - //(RegOpenKeyEx_t)get_proc_address(hAdvapi, "RegOpenKeyExA"); - //if (pRegOpenKey){ - // Pointer to function RegCloseKey - //RegCloseKey_t pRegCloseKey = - //(RegCloseKey_t)get_proc_address(hAdvapi, "RegCloseKey"); - //if (pRegCloseKey){ - // Pointer to function RegQueryValueA - //RegQueryValueEx_t pRegQueryValue = - //(RegQueryValueEx_t)get_proc_address(hAdvapi, "RegQueryValueExA"); - //if (pRegQueryValue){ - //Open the key - void *key; - //if ((*pRegOpenKey)( hkey_local_machine - //, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" - //, 0 - //, key_query_value - //, &key) == 0){ - //reg_closer key_closer(pRegCloseKey, key); - if (reg_open_key_ex( hkey_local_machine - , "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" - , 0 - , key_query_value - , &key) == 0){ - reg_closer key_closer(key); - - //Obtain the value - unsigned long size; - unsigned long type; - const char *const reg_value = "Common AppData"; - //long err = (*pRegQueryValue)( key, reg_value, 0, &type, 0, &size); - long err = reg_query_value_ex( key, reg_value, 0, &type, 0, &size); - if(!err){ - //Size includes terminating NULL - s.resize(size); - //err = (*pRegQueryValue)( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size); - err = reg_query_value_ex( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size); - if(!err) - s.erase(s.end()-1); - (void)err; - } - } - //} - //} - //} - //} + void *key; + if (reg_open_key_ex( hkey_local_machine + , "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" + , 0 + , key_query_value + , &key) == 0){ + reg_closer key_closer(key); + + //Obtain the value + unsigned long size; + unsigned long type; + const char *const reg_value = "Common AppData"; + //long err = (*pRegQueryValue)( key, reg_value, 0, &type, 0, &size); + long err = reg_query_value_ex( key, reg_value, 0, &type, 0, &size); + if(!err){ + //Size includes terminating NULL + s.resize(size); + //err = (*pRegQueryValue)( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size); + err = reg_query_value_ex( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size); + if(!err) + s.erase(s.end()-1); + (void)err; + } + } } - inline void get_registry_value(const char *folder, const char *value_key, std::vector<unsigned char> &s) { s.clear(); - //void *hAdvapi = load_library("Advapi32.dll"); - //if (hAdvapi){ - //library_unloader unloader(hAdvapi); - // Pointer to function RegOpenKeyA - //RegOpenKeyEx_t pRegOpenKey = - //(RegOpenKeyEx_t)get_proc_address(hAdvapi, "RegOpenKeyExA"); - //if (pRegOpenKey){ - // Pointer to function RegCloseKey - //RegCloseKey_t pRegCloseKey = - //(RegCloseKey_t)get_proc_address(hAdvapi, "RegCloseKey"); - //if (pRegCloseKey){ - // Pointer to function RegQueryValueA - //RegQueryValueEx_t pRegQueryValue = - //(RegQueryValueEx_t)get_proc_address(hAdvapi, "RegQueryValueExA"); - //if (pRegQueryValue){ - //Open the key - void *key; - //if ((*pRegOpenKey)( hkey_local_machine - //, folder - //, 0 - //, key_query_value - //, &key) == 0){ - //reg_closer key_closer(pRegCloseKey, key); - if (reg_open_key_ex( hkey_local_machine - , folder - , 0 - , key_query_value - , &key) == 0){ - reg_closer key_closer(key); - - //Obtain the value - unsigned long size; - unsigned long type; - const char *const reg_value = value_key; - //long err = (*pRegQueryValue)( key, reg_value, 0, &type, 0, &size); - long err = reg_query_value_ex( key, reg_value, 0, &type, 0, &size); - if(!err){ - //Size includes terminating NULL - s.resize(size); - //err = (*pRegQueryValue)( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size); - err = reg_query_value_ex( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size); - if(!err) - s.erase(s.end()-1); - (void)err; - } - } - //} - //} - //} - //} + void *key; + if (reg_open_key_ex( hkey_local_machine + , folder + , 0 + , key_query_value + , &key) == 0){ + reg_closer key_closer(key); + + //Obtain the value + unsigned long size; + unsigned long type; + const char *const reg_value = value_key; + //long err = (*pRegQueryValue)( key, reg_value, 0, &type, 0, &size); + long err = reg_query_value_ex( key, reg_value, 0, &type, 0, &size); + if(!err){ + //Size includes terminating NULL + s.resize(size); + //err = (*pRegQueryValue)( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size); + err = reg_query_value_ex( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size); + if(!err) + s.erase(s.end()-1); + (void)err; + } + } } struct co_uninitializer -{ ~co_uninitializer() { CoUninitialize(); } }; +{ + co_uninitializer(bool b_uninitialize) + : m_b_uninitialize(b_uninitialize) + {} + + ~co_uninitializer() + { + if(m_b_uninitialize){ + CoUninitialize(); + } + } + + private: + const bool m_b_uninitialize; +}; template<class Object> struct com_releaser @@ -1615,29 +1661,32 @@ struct com_releaser inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_class, const wchar_t *wmi_class_var) { //See example http://msdn.microsoft.com/en-us/library/aa390423%28v=VS.85%29.aspx - long co_init_ret = CoInitialize(0); - if(co_init_ret != S_OK_BIPC && co_init_ret != S_FALSE_BIPC) + // + //See BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL definition if you need to change the + //default value of this macro in your application + long co_init_ret = CoInitializeEx(0, BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL); + if(co_init_ret != S_OK_BIPC && co_init_ret != S_FALSE_BIPC && co_init_ret != RPC_E_CHANGED_MODE_BIPC) return false; - co_uninitializer co_initialize_end; + co_uninitializer co_initialize_end(co_init_ret != RPC_E_CHANGED_MODE_BIPC); (void)co_initialize_end; bool bRet = false; long sec_init_ret = CoInitializeSecurity - ( 0 //pVoid - ,-1 //cAuthSvc - , 0 //asAuthSvc - , 0 //pReserved1 - , RPC_C_AUTHN_LEVEL_PKT_BIPC //dwAuthnLevel - , RPC_C_IMP_LEVEL_IMPERSONATE_BIPC //dwImpLevel - , 0 //pAuthList - , EOAC_NONE_BIPC //dwCapabilities - , 0 //pReserved3 + ( 0 //pVoid + ,-1 //cAuthSvc + , 0 //asAuthSvc + , 0 //pReserved1 + , RPC_C_AUTHN_LEVEL_PKT_BIPC //dwAuthnLevel + , RPC_C_IMP_LEVEL_IMPERSONATE_BIPC //dwImpLevel + , 0 //pAuthList + , EOAC_NONE_BIPC //dwCapabilities + , 0 //pReserved3 ); if( 0 == sec_init_ret || RPC_E_TOO_LATE_BIPC == sec_init_ret) { IWbemLocator_BIPC * pIWbemLocator = 0; const wchar_t * bstrNamespace = L"root\\cimv2"; - + if( 0 != CoCreateInstance( CLSID_WbemAdministrativeLocator, 0, @@ -1645,7 +1694,7 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ IID_IUnknown, (void **)&pIWbemLocator)){ return false; } - + com_releaser<IWbemLocator_BIPC> IWbemLocator_releaser(pIWbemLocator); IWbemServices_BIPC *pWbemServices = 0; @@ -1677,7 +1726,7 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ ){ return false; } - + com_releaser<IWbemServices_BIPC> IWbemServices_releaser(pWbemServices); strValue.clear(); @@ -1757,9 +1806,40 @@ inline bool is_directory(const char *path) (attrib & file_attribute_directory)); } -} //namespace winapi +inline bool get_file_mapping_size(void *file_mapping_hnd, __int64 &size) +{ + NtQuerySection_t pNtQuerySection = + (NtQuerySection_t)dll_func::get(dll_func::NtQuerySection); + //Obtain file name + interprocess_section_basic_information info; + unsigned long ntstatus = + pNtQuerySection(file_mapping_hnd, section_basic_information, &info, sizeof(info), 0); + if(ntstatus){ + return false; + } + size = info.section_size; + return true; +} + +inline bool get_semaphore_info(void *handle, long &count, long &limit) +{ + winapi::interprocess_semaphore_basic_information info; + winapi::NtQuerySemaphore_t pNtQuerySemaphore = + (winapi::NtQuerySemaphore_t)dll_func::get(winapi::dll_func::NtQuerySemaphore); + unsigned int ret_len; + long status = pNtQuerySemaphore(handle, winapi::semaphore_basic_information, &info, sizeof(info), &ret_len); + if(status){ + return false; + } + count = info.count; + limit = info.limit; + return true; +} + + +} //namespace winapi } //namespace interprocess -} //namespace boost +} //namespace boost #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/detail/windows_intermodule_singleton.hpp b/boost/interprocess/detail/windows_intermodule_singleton.hpp new file mode 100644 index 0000000000..a716e270a7 --- /dev/null +++ b/boost/interprocess/detail/windows_intermodule_singleton.hpp @@ -0,0 +1,306 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP +#define BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP + +#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> + +#if !defined(BOOST_INTERPROCESS_WINDOWS) + #error "This header can't be included from non-windows operating systems" +#endif + +#include <boost/assert.hpp> +#include <boost/interprocess/detail/intermodule_singleton_common.hpp> +#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp> +#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp> +#include <boost/interprocess/sync/scoped_lock.hpp> +#include <boost/cstdint.hpp> +#include <string> +#include <map> + +namespace boost{ +namespace interprocess{ +namespace ipcdetail{ + +namespace intermodule_singleton_helpers { + +//This global map will be implemented using 3 sync primitives: +// +//1) A named mutex that will implement global mutual exclusion between +// threads from different modules/dlls +// +//2) A semaphore that will act as a global counter for modules attached to the global map +// so that the global map can be destroyed when the last module is detached. +// +//3) A semaphore that will be hacked to hold the address of a heap-allocated map in the +// max and current semaphore count. +class windows_semaphore_based_map +{ + typedef std::map<std::string, ref_count_ptr> map_type; + + public: + windows_semaphore_based_map() + { + map_type *m = new map_type; + boost::uint32_t initial_count = 0; + boost::uint32_t max_count = 0; + + //Windows user address space sizes: + //32 bit windows: [32 bit processes] 2GB or 3GB (31/32 bits) + //64 bit windows: [32 bit processes] 2GB or 4GB (31/32 bits) + // [64 bit processes] 2GB or 8TB (31/43 bits) + // + //Windows semaphores use 'long' parameters (32 bits in LLP64 data model) and + //those values can't be negative, so we have 31 bits to store something + //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). + //The max count will hold the pointer value and current semaphore count + //will be zero. + // + //Relying in UB with a cast through union, but all known windows compilers + //accept this (C11 also accepts this). + union caster_union + { + void *addr; + boost::uint32_t addr_uint32; + } caster; + caster.addr = m; + //memory is at least 4 byte aligned in windows + BOOST_ASSERT((caster.addr_uint32 & boost::uint32_t(3)) == 0); + max_count = caster.addr_uint32 >> 2; + } + else if(sizeof(void*) == sizeof(boost::uint64_t)){ + //Relying in UB with a cast through union, but all known windows compilers + //accept this (C11 accepts this). + union caster_union + { + void *addr; + boost::uint64_t addr_uint64; + } caster; + caster.addr = m; + //We'll encode the address using 30 bits in each 32 bit high and low parts. + //High part will be the sem max count, low part will be the sem initial count. + //(restrictions: max count > 0, initial count >= 0 and max count >= initial count): + // + // - Low part will be shifted two times (4 byte alignment) so that top + // two bits are cleared (the top one for sign, the next one to + // assure low part value is always less than the high part value. + // - The top bit of the high part will be cleared and the next bit will be 1 + // (so high part is always bigger than low part due to the quasi-top bit). + // + // This means that the addresses we can store must be 4 byte aligned + // and less than 1 ExbiBytes ( 2^60 bytes, ~1 ExaByte). User-level address space in Windows 64 + // is much less than this (8TB, 2^43 bytes): "1 EByte (or it was 640K?) ought to be enough for anybody" ;-). + caster.addr = m; + BOOST_ASSERT((caster.addr_uint64 & boost::uint64_t(3)) == 0); + max_count = boost::uint32_t(caster.addr_uint64 >> 32); + initial_count = boost::uint32_t(caster.addr_uint64); + initial_count = initial_count/4; + //Make sure top two bits are zero + BOOST_ASSERT((max_count & boost::uint32_t(0xC0000000)) == 0); + //Set quasi-top bit + max_count |= boost::uint32_t(0x40000000); + } + bool created = false; + const permissions & perm = permissions(); + std::string pid_creation_time, name; + get_pid_creation_time_str(pid_creation_time); + name = "bipc_gmap_sem_lock_"; + name += pid_creation_time; + bool success = m_mtx_lock.open_or_create(name.c_str(), perm); + name = "bipc_gmap_sem_count_"; + name += pid_creation_time; + scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock); + { + success = success && m_sem_count.open_or_create + ( name.c_str(), static_cast<long>(0), winapi_semaphore_wrapper::MaxCount, perm, created); + name = "bipc_gmap_sem_map_"; + name += pid_creation_time; + success = success && m_sem_map.open_or_create + (name.c_str(), initial_count, max_count, perm, created); + if(!success){ + //winapi_xxx wrappers do the cleanup... + throw int(0); + } + if(!created){ + delete m; + } + else{ + BOOST_ASSERT(&get_map_unlocked() == m); + } + m_sem_count.post(); + } + } + + map_type &get_map_unlocked() + { + if(sizeof(void*) == sizeof(boost::uint32_t)){ + union caster_union + { + void *addr; + boost::uint32_t addr_uint32; + } caster; + caster.addr = 0; + caster.addr_uint32 = m_sem_map.limit(); + caster.addr_uint32 = caster.addr_uint32 << 2; + return *static_cast<map_type*>(caster.addr); + } + else{ + union caster_union + { + void *addr; + boost::uint64_t addr_uint64; + } caster; + boost::uint32_t max_count(m_sem_map.limit()), initial_count(m_sem_map.value()); + //Clear quasi-top bit + max_count &= boost::uint32_t(0xBFFFFFFF); + caster.addr_uint64 = max_count; + caster.addr_uint64 = caster.addr_uint64 << 32; + caster.addr_uint64 |= boost::uint64_t(initial_count) << 2; + return *static_cast<map_type*>(caster.addr); + } + } + + ref_count_ptr *find(const char *name) + { + 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)); + if(it != map.end()){ + return &it->second; + } + else{ + return 0; + } + } + + ref_count_ptr * insert(const char *name, const ref_count_ptr &ref) + { + 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; + return &it->second; + } + + bool erase(const char *name) + { + scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock); + map_type &map = this->get_map_unlocked(); + return map.erase(std::string(name)) != 0; + } + + template<class F> + void atomic_func(F &f) + { + scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock); + f(); + } + + ~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(); + } + //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; + winapi_semaphore_wrapper m_sem_count; +}; + +template<> +struct thread_safe_global_map_dependant<windows_semaphore_based_map> +{ + static void apply_gmem_erase_logic(const char *, const char *){} + + static bool remove_old_gmem() + { return true; } + + struct lock_file_logic + { + lock_file_logic(windows_semaphore_based_map &) + : retry_with_new_map(false) + {} + + void operator()(void){} + bool retry() const { return retry_with_new_map; } + private: + const bool retry_with_new_map; + }; + + static void construct_map(void *addr) + { + ::new (addr)windows_semaphore_based_map; + } + + struct unlink_map_logic + { + unlink_map_logic(windows_semaphore_based_map &) + {} + void operator()(){} + }; + + static ref_count_ptr *find(windows_semaphore_based_map &map, const char *name) + { + return map.find(name); + } + + static ref_count_ptr * insert(windows_semaphore_based_map &map, const char *name, const ref_count_ptr &ref) + { + return map.insert(name, ref); + } + + static bool erase(windows_semaphore_based_map &map, const char *name) + { + return map.erase(name); + } + + template<class F> + static void atomic_func(windows_semaphore_based_map &map, F &f) + { + map.atomic_func(f); + } +}; + +} //namespace intermodule_singleton_helpers { + +template<typename C, bool LazyInit = true, bool Phoenix = true> +class windows_intermodule_singleton + : public intermodule_singleton_impl + < C + , LazyInit + , Phoenix + , intermodule_singleton_helpers::windows_semaphore_based_map + > +{}; + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //#ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP diff --git a/boost/interprocess/detail/workaround.hpp b/boost/interprocess/detail/workaround.hpp index 896a2208a2..884b8680a6 100644 --- a/boost/interprocess/detail/workaround.hpp +++ b/boost/interprocess/detail/workaround.hpp @@ -13,43 +13,34 @@ #include <boost/interprocess/detail/config_begin.hpp> -#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) - -#define BOOST_INTERPROCESS_WINDOWS - -/* -#if !defined(_MSC_EXTENSIONS) -#error "Turn on Microsoft language extensions (_MSC_EXTENSIONS) to be able to call Windows API functions" -#endif -*/ - -#endif - -#if !defined(BOOST_INTERPROCESS_WINDOWS) - +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + #define BOOST_INTERPROCESS_WINDOWS + #define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION + #define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME +#else #include <unistd.h> - #if ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0) - //Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it. - //Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seems to work. - # if !defined(__CYGWIN__) && !defined(__APPLE__) - # define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED - # endif + #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__) + #define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED + #endif + #endif + + #if defined(_POSIX_BARRIERS) && ((_POSIX_BARRIERS - 0) > 0) + #define BOOST_INTERPROCESS_POSIX_BARRIERS #endif - - #if ((_POSIX_BARRIERS - 0) > 0) - # define BOOST_INTERPROCESS_POSIX_BARRIERS - # endif - - #if ((_POSIX_SEMAPHORES - 0) > 0) - # define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES - # if defined(__CYGWIN__) - #define BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK - # endif + + #if defined(_POSIX_SEMAPHORES) && ((_POSIX_SEMAPHORES - 0) > 0) + #define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES + #if defined(__CYGWIN__) + #define BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK + #endif //Some platforms have a limited (name length) named semaphore support #elif (defined(__FreeBSD__) && (__FreeBSD__ >= 4)) || defined(__APPLE__) - # define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES - #endif + #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)) ||\ @@ -60,87 +51,83 @@ ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))||\ ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64)) #define BOOST_INTERPROCESS_UNIX_64_BIT_OR_BIGGER_OFF_T - #else #endif //Check for XSI shared memory objects. They are available in nearly all UNIX platforms #if !defined(__QNXNTO__) - # define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS #endif - #if ((_POSIX_SHARED_MEMORY_OBJECTS - 0) > 0) - # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS + #if defined(_POSIX_SHARED_MEMORY_OBJECTS) && ((_POSIX_SHARED_MEMORY_OBJECTS - 0) > 0) + #define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS #else - //VMS and MACOS don't define it but the have shm_open/close interface - # if defined(__vms) - # if __CRTL_VER >= 70200000 - # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS - # endif - //Mac OS has some non-conformant features like names limited to SHM_NAME_MAX - # elif defined (__APPLE__) -// # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS -// # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW - # endif + //VMS and MACOS don't define it but they have shm_open/close interface + #if defined(__vms) + #if __CRTL_VER >= 70200000 + #define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS + #endif + //Mac OS has some non-conformant features like names limited to SHM_NAME_MAX + #elif defined (__APPLE__) + //#define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS + //#define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW + #endif #endif //Now check if we have only XSI shared memory #if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) &&\ !defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS) - //# define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS_ONLY + //#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS_ONLY #endif - #if ((_POSIX_TIMEOUTS - 0) > 0) - # define BOOST_INTERPROCESS_POSIX_TIMEOUTS - #endif - + #if defined(_POSIX_TIMEOUTS) && ((_POSIX_TIMEOUTS - 0) > 0) + #define BOOST_INTERPROCESS_POSIX_TIMEOUTS + #endif #ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS //Some systems have filesystem-based resources, so the //portable "/shmname" format does not work due to permission issues //For those systems we need to form a path to a temporary directory: // hp-ux tru64 vms freebsd - #if defined(__hpux) || defined(__osf__) || defined(__vms) || (defined(__FreeBSD__) && (__FreeBSD__ < 7)) - #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY + #if defined(__hpux) || defined(__osf__) || defined(__vms) || (defined(__FreeBSD__) && (__FreeBSD__ < 7)) + #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY #elif defined(__FreeBSD__) - #define BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY + #define BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY #endif #endif #ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES #if defined(__osf__) || defined(__vms) - #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES + #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES #endif #endif - #if ((_POSIX_VERSION + 0)>= 200112L || (_XOPEN_VERSION + 0)>= 500) - #define BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES + #if defined(_POSIX_VERSION) && defined(_XOPEN_VERSION) && \ + (((_POSIX_VERSION + 0)>= 200112L || (_XOPEN_VERSION + 0)>= 500)) + #define BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES #endif -#endif + #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) + #define BOOST_INTERPROCESS_BSD_DERIVATIVE + #include <sys/sysctl.h> + #if defined(CTL_KERN) && defined (KERN_BOOTTIME) + //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME + #endif + #endif +#endif //!defined(BOOST_INTERPROCESS_WINDOWS) -#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)\ - && !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL) -#define BOOST_INTERPROCESS_PERFECT_FORWARDING +#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES) + #define BOOST_INTERPROCESS_PERFECT_FORWARDING #endif //Now declare some Boost.Interprocess features depending on the implementation - #if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK) - -#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES - -#endif - -#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK) - -#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES -#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES - + #define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES + #define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES #endif // Timeout duration use if BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING is set #ifndef BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS -#define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000 + #define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000 #endif #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/detail/xsi_shared_memory_device.hpp b/boost/interprocess/detail/xsi_shared_memory_device.hpp index d2e2bf2ce6..ef4b009bc1 100644 --- a/boost/interprocess/detail/xsi_shared_memory_device.hpp +++ b/boost/interprocess/detail/xsi_shared_memory_device.hpp @@ -46,7 +46,7 @@ class xsi_shared_memory_device { /// @cond BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper) - /// @endcond + /// @endcond public: @@ -74,10 +74,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 @@ -168,7 +168,7 @@ inline xsi_shared_memory_device::xsi_shared_memory_device() : m_shm(), m_mode(invalid_mode), m_name() {} -inline xsi_shared_memory_device::~xsi_shared_memory_device() +inline xsi_shared_memory_device::~xsi_shared_memory_device() {} inline const char *xsi_shared_memory_device::get_name() const @@ -178,7 +178,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 diff --git a/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp b/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp index d74d9664a5..14811e7e62 100644 --- a/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp +++ b/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp @@ -40,7 +40,7 @@ class xsi_shared_memory_file_wrapper { /// @cond BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper) - /// @endcond + /// @endcond public: xsi_shared_memory_file_wrapper() : xsi_shared_memory() {} @@ -61,10 +61,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 e36b8e4e66..9eed55a29b 100644 --- a/boost/interprocess/errors.hpp +++ b/boost/interprocess/errors.hpp @@ -11,7 +11,7 @@ ////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002 Beman Dawes -// Copyright (C) 2001 Dietmar Kuehl +// Copyright (C) 2001 Dietmar Kuehl // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy // at http://www.boost.org/LICENSE_1_0.txt) @@ -64,16 +64,16 @@ inline int system_error_code() // artifact of POSIX and WINDOWS error reporting inline void fill_system_message(int sys_err_code, std::string &str) { void *lpMsgBuf; - winapi::format_message( - winapi::format_message_allocate_buffer | - winapi::format_message_from_system | + winapi::format_message( + winapi::format_message_allocate_buffer | + winapi::format_message_from_system | winapi::format_message_ignore_inserts, 0, sys_err_code, winapi::make_lang_id(winapi::lang_neutral, winapi::sublang_default), // Default language reinterpret_cast<char *>(&lpMsgBuf), 0, - 0 + 0 ); str += static_cast<const char*>(lpMsgBuf); winapi::local_free( lpMsgBuf ); // free the buffer @@ -123,7 +123,7 @@ typedef int native_error_t; struct ec_xlate { native_error_t sys_ec; - error_code_t ec; + error_code_t ec; }; static const ec_xlate ec_table[] = @@ -183,9 +183,9 @@ static const ec_xlate ec_table[] = }; 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); + *end = cur + sizeof(ec_table)/sizeof(ec_xlate); for (;cur != end; ++cur ){ if ( err == cur->sys_ec ) return cur->ec; } diff --git a/boost/interprocess/file_mapping.hpp b/boost/interprocess/file_mapping.hpp index 3bad98fca1..2a4e4cca00 100644 --- a/boost/interprocess/file_mapping.hpp +++ b/boost/interprocess/file_mapping.hpp @@ -41,27 +41,27 @@ class file_mapping //!Does not throw file_mapping(); - //!Opens a file mapping of file "filename", starting in offset - //!"file_offset", and the mapping's size will be "size". The mapping + //!Opens a file mapping of file "filename", starting in offset + //!"file_offset", and the mapping's size will be "size". The mapping //!can be opened for read-only "read_only" or read-write "read_write" //!modes. Throws interprocess_exception on error. file_mapping(const char *filename, mode_t mode); - //!Moves the ownership of "moved"'s file mapping object to *this. - //!After the call, "moved" does not represent any file mapping object. + //!Moves the ownership of "moved"'s file mapping object to *this. + //!After the call, "moved" does not represent any file mapping object. //!Does not throw file_mapping(BOOST_RV_REF(file_mapping) moved) : m_handle(file_handle_t(ipcdetail::invalid_file())) { this->swap(moved); } //!Moves the ownership of "moved"'s file mapping to *this. - //!After the call, "moved" does not represent any file mapping. + //!After the call, "moved" does not represent any file mapping. //!Does not throw file_mapping &operator=(BOOST_RV_REF(file_mapping) moved) { file_mapping tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps to file_mappings. @@ -100,21 +100,21 @@ class file_mapping /// @endcond }; -inline file_mapping::file_mapping() +inline file_mapping::file_mapping() : m_handle(file_handle_t(ipcdetail::invalid_file())) {} -inline file_mapping::~file_mapping() +inline file_mapping::~file_mapping() { this->priv_close(); } inline const char *file_mapping::get_name() const { return m_filename.c_str(); } inline void file_mapping::swap(file_mapping &other) -{ +{ std::swap(m_handle, other.m_handle); std::swap(m_mode, other.m_mode); - m_filename.swap(other.m_filename); + m_filename.swap(other.m_filename); } inline mapping_handle_t file_mapping::get_mapping_handle() const diff --git a/boost/interprocess/indexes/iset_index.hpp b/boost/interprocess/indexes/iset_index.hpp index 966239290a..8fc91466f3 100644 --- a/boost/interprocess/indexes/iset_index.hpp +++ b/boost/interprocess/indexes/iset_index.hpp @@ -34,17 +34,17 @@ namespace interprocess { template <class MapConfig> struct iset_index_aux { - typedef typename + typedef typename MapConfig::segment_manager_base segment_manager_base; - typedef typename + typedef typename segment_manager_base::void_pointer void_pointer; typedef typename bi::make_set_base_hook < bi::void_pointer<void_pointer> , bi::optimize_size<true> >::type derivation_hook; - typedef typename MapConfig::template + typedef typename MapConfig::template intrusive_value_type<derivation_hook>::type value_type; typedef std::less<value_type> value_compare; typedef typename bi::make_set @@ -82,20 +82,20 @@ class iset_index struct intrusive_key_value_less { bool operator()(const intrusive_compare_key_type &i, const value_type &b) const - { + { std::size_t blen = b.name_length(); - return (i.m_len < blen) || - (i.m_len == blen && - std::char_traits<char_type>::compare + return (i.m_len < blen) || + (i.m_len == blen && + 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 - { + { std::size_t blen = b.name_length(); - return (blen < i.m_len) || + return (blen < i.m_len) || (blen == i.m_len && - std::char_traits<char_type>::compare + std::char_traits<char_type>::compare (b.name(), i.mp_str, i.m_len) < 0); } }; @@ -143,7 +143,7 @@ struct is_intrusive_index /// @endcond } //namespace interprocess { -} //namespace boost +} //namespace boost #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/indexes/iunordered_set_index.hpp b/boost/interprocess/indexes/iunordered_set_index.hpp index ef1ae79d3b..3c5f85526c 100644 --- a/boost/interprocess/indexes/iunordered_set_index.hpp +++ b/boost/interprocess/indexes/iunordered_set_index.hpp @@ -35,17 +35,17 @@ namespace boost { namespace interprocess { template <class MapConfig> struct iunordered_set_index_aux { - typedef typename + typedef typename MapConfig::segment_manager_base segment_manager_base; - typedef typename + typedef typename segment_manager_base::void_pointer void_pointer; typedef typename bi::make_unordered_set_base_hook < bi::void_pointer<void_pointer> >::type derivation_hook; - typedef typename MapConfig::template + typedef typename MapConfig::template intrusive_value_type<derivation_hook>::type value_type; typedef typename MapConfig:: @@ -58,23 +58,23 @@ 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 + (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 + (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 + (std::char_traits<char_type>::compare (b1.name(), b2.name(), b1.name_length()) == 0); } }; @@ -119,7 +119,7 @@ struct iunordered_set_index_aux /// @endcond //!Index type based in boost::intrusive::set. -//!Just derives from boost::intrusive::set +//!Just derives from boost::intrusive::set //!and defines the interface needed by managed memory segments template <class MapConfig> class iunordered_set_index @@ -135,9 +135,9 @@ class iunordered_set_index typedef typename index_aux::equal_function equal_function; typedef typename index_aux::hash_function hash_function; typedef typename MapConfig::char_type char_type; - typedef typename + typedef typename iunordered_set_index_aux<MapConfig>::allocator_type allocator_type; - typedef typename + typedef typename iunordered_set_index_aux<MapConfig>::allocator_holder allocator_holder; /// @endcond @@ -290,7 +290,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 +337,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. diff --git a/boost/interprocess/indexes/map_index.hpp b/boost/interprocess/indexes/map_index.hpp index ffea73e8d9..1bfc7ce310 100644 --- a/boost/interprocess/indexes/map_index.hpp +++ b/boost/interprocess/indexes/map_index.hpp @@ -48,7 +48,7 @@ struct map_index_aux } //namespace ipcdetail { -//!Index type based in boost::interprocess::map. Just derives from boost::interprocess::map +//!Index type based in boost::interprocess::map. Just derives from boost::interprocess::map //!and defines the interface needed by managed memory segments template <class MapConfig> class map_index diff --git a/boost/interprocess/indexes/null_index.hpp b/boost/interprocess/indexes/null_index.hpp index 81c88be79b..a0353b101c 100644 --- a/boost/interprocess/indexes/null_index.hpp +++ b/boost/interprocess/indexes/null_index.hpp @@ -16,7 +16,7 @@ #include <boost/interprocess/offset_ptr.hpp> //!\file -//!Describes a null index adaptor, so that if we don't want to construct +//!Describes a null index adaptor, so that if we don't want to construct //!named objects, we can use this null index type to save resources. namespace boost { diff --git a/boost/interprocess/indexes/unordered_map_index.hpp b/boost/interprocess/indexes/unordered_map_index.hpp index a14fa1d4a7..7cf4b85e65 100644 --- a/boost/interprocess/indexes/unordered_map_index.hpp +++ b/boost/interprocess/indexes/unordered_map_index.hpp @@ -69,7 +69,7 @@ class unordered_map_index /// @cond typedef unordered_map_index_aux<MapConfig> index_aux; typedef typename index_aux::index_t base_type; - typedef typename + typedef typename MapConfig::segment_manager_base segment_manager_base; /// @endcond diff --git a/boost/interprocess/interprocess_fwd.hpp b/boost/interprocess/interprocess_fwd.hpp index 2b3e3eba07..68fd89fb91 100644 --- a/boost/interprocess/interprocess_fwd.hpp +++ b/boost/interprocess/interprocess_fwd.hpp @@ -214,7 +214,7 @@ template <class CharType ,template<class IndexConfig> class IndexType> class basic_managed_shared_memory; -typedef basic_managed_shared_memory +typedef basic_managed_shared_memory <char ,rbtree_best_fit<mutex_family> ,iset_index> @@ -238,7 +238,7 @@ template <class CharType ,template<class IndexConfig> class IndexType> class basic_managed_windows_shared_memory; -typedef basic_managed_windows_shared_memory +typedef basic_managed_windows_shared_memory <char ,rbtree_best_fit<mutex_family> ,iset_index> @@ -259,7 +259,7 @@ template <class CharType ,template<class IndexConfig> class IndexType> class basic_managed_xsi_shared_memory; -typedef basic_managed_xsi_shared_memory +typedef basic_managed_xsi_shared_memory <char ,rbtree_best_fit<mutex_family> ,iset_index> diff --git a/boost/interprocess/ipc/message_queue.hpp b/boost/interprocess/ipc/message_queue.hpp index d3846afb7c..67dd574f61 100644 --- a/boost/interprocess/ipc/message_queue.hpp +++ b/boost/interprocess/ipc/message_queue.hpp @@ -66,24 +66,24 @@ class message_queue_t //!the maximum number of messages will be "max_num_msg" and the maximum message size //!will be "max_msg_size". Throws on error and if the queue was previously created. message_queue_t(create_only_t create_only, - const char *name, - size_type max_num_msg, + const char *name, + size_type max_num_msg, size_type max_msg_size, const permissions &perm = permissions()); - //!Opens or creates a process shared message queue with name "name". - //!If the queue is created, the maximum number of messages will be "max_num_msg" - //!and the maximum message size will be "max_msg_size". If queue was previously + //!Opens or creates a process shared message queue with name "name". + //!If the queue is created, the maximum number of messages will be "max_num_msg" + //!and the maximum message size will be "max_msg_size". If queue was previously //!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters //!are ignored. Throws on error. message_queue_t(open_or_create_t open_or_create, - const char *name, - size_type max_num_msg, + const char *name, + size_type max_num_msg, size_type max_msg_size, const permissions &perm = permissions()); - //!Opens a previously created process shared message queue with name "name". - //!If the queue was not previously created or there are no free resources, + //!Opens a previously created process shared message queue with name "name". + //!If the queue was not previously created or there are no free resources, //!throws an error. message_queue_t(open_only_t open_only, const char *name); @@ -95,65 +95,65 @@ class message_queue_t //!this resource. The resource can still be opened again calling //!the open constructor overload. To erase the message queue from the system //!use remove(). - ~message_queue_t(); + ~message_queue_t(); - //!Sends a message stored in buffer "buffer" with size "buffer_size" in the + //!Sends a message stored in buffer "buffer" with size "buffer_size" in the //!message queue with priority "priority". If the message queue is full //!the sender is blocked. Throws interprocess_error on error.*/ - void send (const void *buffer, size_type buffer_size, + void send (const void *buffer, size_type buffer_size, unsigned int priority); - //!Sends a message stored in buffer "buffer" with size "buffer_size" through the + //!Sends a message stored in buffer "buffer" with size "buffer_size" through the //!message queue with priority "priority". If the message queue is full //!the sender is not blocked and returns false, otherwise returns true. //!Throws interprocess_error on error. - bool try_send (const void *buffer, size_type buffer_size, + bool try_send (const void *buffer, size_type buffer_size, unsigned int priority); - //!Sends a message stored in buffer "buffer" with size "buffer_size" in the + //!Sends a message stored in buffer "buffer" with size "buffer_size" in the //!message queue with priority "priority". If the message queue is full //!the sender retries until time "abs_time" is reached. Returns true if //!the message has been successfully sent. Returns false if timeout is reached. //!Throws interprocess_error on error. - bool timed_send (const void *buffer, size_type buffer_size, + bool timed_send (const void *buffer, size_type buffer_size, unsigned int priority, const boost::posix_time::ptime& abs_time); - //!Receives a message from the message queue. The message is stored in buffer - //!"buffer", which has size "buffer_size". The received message has size + //!Receives a message from the message queue. The message is stored in buffer + //!"buffer", which has size "buffer_size". The received message has size //!"recvd_size" and priority "priority". If the message queue is empty //!the receiver is blocked. Throws interprocess_error on error. - void receive (void *buffer, size_type buffer_size, + void receive (void *buffer, size_type buffer_size, size_type &recvd_size,unsigned int &priority); - //!Receives a message from the message queue. The message is stored in buffer - //!"buffer", which has size "buffer_size". The received message has size + //!Receives a message from the message queue. The message is stored in buffer + //!"buffer", which has size "buffer_size". The received message has size //!"recvd_size" and priority "priority". If the message queue is empty //!the receiver is not blocked and returns false, otherwise returns true. //!Throws interprocess_error on error. - bool try_receive (void *buffer, size_type buffer_size, + bool try_receive (void *buffer, size_type buffer_size, size_type &recvd_size,unsigned int &priority); - //!Receives a message from the message queue. The message is stored in buffer - //!"buffer", which has size "buffer_size". The received message has size + //!Receives a message from the message queue. The message is stored in buffer + //!"buffer", which has size "buffer_size". The received message has size //!"recvd_size" and priority "priority". If the message queue is empty //!the receiver retries until time "abs_time" is reached. Returns true if //!the message has been successfully sent. Returns false if timeout is reached. //!Throws interprocess_error on error. - bool timed_receive (void *buffer, size_type buffer_size, + bool timed_receive (void *buffer, size_type buffer_size, size_type &recvd_size,unsigned int &priority, const boost::posix_time::ptime &abs_time); //!Returns the maximum number of messages allowed by the queue. The message - //!queue must be opened or created previously. Otherwise, returns 0. + //!queue must be opened or created previously. Otherwise, returns 0. //!Never throws size_type get_max_msg() const; //!Returns the maximum size of message allowed by the queue. The message - //!queue must be opened or created previously. Otherwise, returns 0. + //!queue must be opened or created previously. Otherwise, returns 0. //!Never throws size_type get_max_msg_size() const; - //!Returns the number of messages currently stored. + //!Returns the number of messages currently stored. //!Never throws size_type get_num_msg(); @@ -161,16 +161,16 @@ class message_queue_t //!Returns false on error. Never throws static bool remove(const char *name); - /// @cond + /// @cond private: typedef boost::posix_time::ptime ptime; bool do_receive(block_t block, - void *buffer, size_type buffer_size, + void *buffer, size_type buffer_size, size_type &recvd_size, unsigned int &priority, const ptime &abs_time); bool do_send(block_t block, - const void *buffer, size_type buffer_size, + const void *buffer, size_type buffer_size, unsigned int priority, const ptime &abs_time); //!Returns the needed memory size for the shared message queue. @@ -187,7 +187,7 @@ namespace ipcdetail { //!This header is the prefix of each message in the queue template<class VoidPointer> -class msg_hdr_t +class msg_hdr_t { typedef VoidPointer void_pointer; typedef typename boost::intrusive:: @@ -212,36 +212,36 @@ class priority_functor rebind_pointer<msg_hdr_t<VoidPointer> >::type msg_hdr_ptr_t; public: - bool operator()(const msg_hdr_ptr_t &msg1, + bool operator()(const msg_hdr_ptr_t &msg1, const msg_hdr_ptr_t &msg2) const { return msg1->priority < msg2->priority; } }; -//!This header is placed in the beginning of the shared memory and contains -//!the data to control the queue. This class initializes the shared memory +//!This header is placed in the beginning of the shared memory and contains +//!the data to control the queue. This class initializes the shared memory //!in the following way: in ascending memory address with proper alignment //!fillings: //! -//!-> mq_hdr_t: +//!-> mq_hdr_t: //! Main control block that controls the rest of the elements //! //!-> 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 +//! An array of pointers with size "max_num_msg" called index. Each pointer +//! points to a preallocated message. The elements of this array are //! reordered in runtime in the following way: //! -//! When the current number of messages is "cur_num_msg", the first +//! When the current number of messages is "cur_num_msg", the first //! "cur_num_msg" pointers point to inserted messages and the rest //! point to free messages. The first "cur_num_msg" pointers are -//! ordered by the priority of the pointed message and by insertion order -//! if two messages have the same priority. So the next message to be +//! ordered by the priority of the pointed message and by insertion order +//! if two messages have the same priority. So the next message to be //! used in a "receive" is pointed by index [cur_num_msg-1] and the first free //! message ready to be used in a "send" operation is index [cur_num_msg]. //! This transforms 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 +252,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:: @@ -266,12 +266,12 @@ class mq_hdr_t rebind_pointer<msg_hdr_ptr_t>::type msg_hdr_ptr_ptr_t; public: - //!Constructor. This object must be constructed in the beginning of the + //!Constructor. This object must be constructed in the beginning of the //!shared memory of the size returned by the function "get_mem_size". //!This constructor initializes the needed resources and creates //!the internal structures like the priority index. This can throw.*/ mq_hdr_t(size_type max_num_msg, size_type max_msg_size) - : m_max_num_msg(max_num_msg), + : m_max_num_msg(max_num_msg), m_max_msg_size(max_msg_size), m_cur_num_msg(0) { this->initialize_memory(); } @@ -298,7 +298,7 @@ class mq_hdr_t //!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]; //Get priority queue's range @@ -312,19 +312,19 @@ class mq_hdr_t ++m_cur_num_msg; } - //!Returns the number of bytes needed to construct a message queue with - //!"max_num_size" maximum number of messages and "max_msg_size" maximum + //!Returns the number of bytes needed to construct a message queue with + //!"max_num_size" maximum number of messages and "max_msg_size" maximum //!message size. Never throws. static size_type get_mem_size (size_type max_msg_size, size_type max_num_msg) { - const size_type + const size_type 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); - return r_hdr_size + r_index_size + (max_num_msg*r_max_msg_size) + + return r_hdr_size + r_index_size + (max_num_msg*r_max_msg_size) + ipcdetail::managed_open_or_create_impl<shared_memory_object>::ManagedOpenOrCreateUserOffset; } @@ -332,7 +332,7 @@ class mq_hdr_t //!message index. Never throws. void initialize_memory() { - const size_type + const size_type 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, @@ -345,7 +345,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; @@ -376,7 +376,7 @@ class mq_hdr_t }; -//!This is the atomic functor to be executed when creating or opening +//!This is the atomic functor to be executed when creating or opening //!shared memory. Never throws template<class VoidPointer> class initialization_func_t @@ -388,7 +388,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, + initialization_func_t(size_type maxmsg = 0, size_type maxmsgsize = 0) : m_maxmsg (maxmsg), m_maxmsgsize(maxmsgsize) {} @@ -403,7 +403,7 @@ class initialization_func_t new (mptr) mq_hdr_t<VoidPointer>(m_maxmsg, m_maxmsgsize); } BOOST_CATCH(...){ - return false; + return false; } BOOST_CATCH_END } @@ -426,13 +426,13 @@ inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPoin template<class VoidPointer> inline message_queue_t<VoidPointer>::message_queue_t(create_only_t create_only, - const char *name, - size_type max_num_msg, + const char *name, + size_type max_num_msg, size_type max_msg_size, const permissions &perm) //Create shared memory and execute functor atomically - : m_shmem(create_only, - name, + : m_shmem(create_only, + name, get_mem_size(max_msg_size, max_num_msg), read_write, static_cast<void*>(0), @@ -443,13 +443,13 @@ inline message_queue_t<VoidPointer>::message_queue_t(create_only_t create_only, template<class VoidPointer> inline message_queue_t<VoidPointer>::message_queue_t(open_or_create_t open_or_create, - const char *name, - size_type max_num_msg, + const char *name, + size_type max_num_msg, size_type max_msg_size, const permissions &perm) //Create shared memory and execute functor atomically - : m_shmem(open_or_create, - name, + : m_shmem(open_or_create, + name, get_mem_size(max_msg_size, max_num_msg), read_write, static_cast<void*>(0), @@ -462,7 +462,7 @@ template<class VoidPointer> inline message_queue_t<VoidPointer>::message_queue_t(open_only_t open_only, const char *name) //Create shared memory and execute functor atomically - : m_shmem(open_only, + : m_shmem(open_only, name, read_write, static_cast<void*>(0), @@ -494,7 +494,7 @@ inline bool message_queue_t<VoidPointer>::timed_send template<class VoidPointer> inline bool message_queue_t<VoidPointer>::do_send(block_t block, - const void *buffer, size_type buffer_size, + const void *buffer, size_type buffer_size, unsigned int priority, const boost::posix_time::ptime &abs_time) { ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address()); @@ -536,7 +536,7 @@ inline bool message_queue_t<VoidPointer>::do_send(block_t block, break; } } - + //Get the first free message from free message queue ipcdetail::msg_hdr_t<VoidPointer> *free_msg = p_hdr->free_msg(); if (free_msg == 0) { @@ -553,7 +553,7 @@ inline bool message_queue_t<VoidPointer>::do_send(block_t block, // 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(); @@ -564,19 +564,19 @@ inline bool message_queue_t<VoidPointer>::do_send(block_t block, } template<class VoidPointer> -inline void message_queue_t<VoidPointer>::receive(void *buffer, size_type buffer_size, +inline void message_queue_t<VoidPointer>::receive(void *buffer, size_type buffer_size, size_type &recvd_size, unsigned int &priority) { this->do_receive(blocking, buffer, buffer_size, recvd_size, priority, ptime()); } template<class VoidPointer> inline bool - message_queue_t<VoidPointer>::try_receive(void *buffer, size_type buffer_size, + message_queue_t<VoidPointer>::try_receive(void *buffer, size_type buffer_size, size_type &recvd_size, unsigned int &priority) { return this->do_receive(non_blocking, buffer, buffer_size, recvd_size, priority, ptime()); } template<class VoidPointer> inline bool - message_queue_t<VoidPointer>::timed_receive(void *buffer, size_type buffer_size, + message_queue_t<VoidPointer>::timed_receive(void *buffer, size_type buffer_size, size_type &recvd_size, unsigned int &priority, const boost::posix_time::ptime &abs_time) { @@ -590,7 +590,7 @@ inline bool template<class VoidPointer> inline bool message_queue_t<VoidPointer>::do_receive(block_t block, - void *buffer, size_type buffer_size, + void *buffer, size_type buffer_size, size_type &recvd_size, unsigned int &priority, const boost::posix_time::ptime &abs_time) { @@ -666,20 +666,20 @@ inline bool 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() -{ +{ ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address()); if(p_hdr){ //--------------------------------------------- @@ -688,7 +688,7 @@ 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> diff --git a/boost/interprocess/managed_external_buffer.hpp b/boost/interprocess/managed_external_buffer.hpp index a2cf47f4e6..e268e57601 100644 --- a/boost/interprocess/managed_external_buffer.hpp +++ b/boost/interprocess/managed_external_buffer.hpp @@ -23,34 +23,34 @@ #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> //!\file -//!Describes a named user memory allocation user class. +//!Describes a named user memory allocation user class. namespace boost { namespace interprocess { -//!A basic user memory named object creation class. Inherits all -//!basic functionality from +//!A basic user memory named object creation class. Inherits all +//!basic functionality from //!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/ template < - class CharType, - class AllocationAlgorithm, + class CharType, + class AllocationAlgorithm, template<class IndexConfig> class IndexType > -class basic_managed_external_buffer +class basic_managed_external_buffer : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType> { /// @cond - typedef ipcdetail::basic_managed_memory_impl + typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType> base_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_external_buffer) /// @endcond - + public: typedef typename base_t::size_type size_type; diff --git a/boost/interprocess/managed_heap_memory.hpp b/boost/interprocess/managed_heap_memory.hpp index 74869bb1f5..87107855f2 100644 --- a/boost/interprocess/managed_heap_memory.hpp +++ b/boost/interprocess/managed_heap_memory.hpp @@ -24,32 +24,32 @@ #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> //!\file -//!Describes a named heap memory allocation user class. +//!Describes a named heap memory allocation user class. namespace boost { namespace interprocess { -//!A basic heap memory named object creation class. Initializes the -//!heap memory segment. Inherits all basic functionality from +//!A basic heap memory named object creation class. Initializes the +//!heap memory segment. Inherits all basic functionality from //!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/ template < - class CharType, - class AllocationAlgorithm, + class CharType, + class AllocationAlgorithm, template<class IndexConfig> class IndexType > -class basic_managed_heap_memory +class basic_managed_heap_memory : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType> { /// @cond private: - typedef ipcdetail::basic_managed_memory_impl + typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType> base_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_heap_memory) /// @endcond @@ -90,16 +90,16 @@ class basic_managed_heap_memory } //!Tries to resize internal heap memory so that - //!we have room for more objects. - //!WARNING: If memory is reallocated, all the objects will + //!we have room for more objects. + //!WARNING: If memory is reallocated, all the objects will //!be binary-copied to the new buffer. To be able to use //!this function, all pointers constructed in this buffer //!must be offset pointers. Otherwise, the result is undefined. //!Returns true if the growth has been successful, so you will - //!have some extra bytes to allocate new objects. If returns + //!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{ @@ -129,7 +129,7 @@ class basic_managed_heap_memory private: //!Frees resources. Never throws. void priv_close() - { + { base_t::destroy_impl(); std::vector<char>().swap(m_heapmem); } diff --git a/boost/interprocess/managed_mapped_file.hpp b/boost/interprocess/managed_mapped_file.hpp index 218fa9783c..5a351adfa5 100644 --- a/boost/interprocess/managed_mapped_file.hpp +++ b/boost/interprocess/managed_mapped_file.hpp @@ -26,23 +26,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> #include <boost/interprocess/indexes/iset_index.hpp> namespace boost { namespace interprocess { -//!A basic mapped file named object creation class. Initializes the -//!mapped file. Inherits all basic functionality from +//!A basic mapped file named object creation class. Initializes the +//!mapped file. Inherits all basic functionality from //!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType> template < - class CharType, - class AllocationAlgorithm, + class CharType, + class AllocationAlgorithm, template<class IndexConfig> class IndexType > -class basic_managed_mapped_file +class basic_managed_mapped_file : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType ,ipcdetail::managed_open_or_create_impl< ipcdetail::file_wrapper @@ -51,7 +51,7 @@ class basic_managed_mapped_file { /// @cond public: - typedef ipcdetail::basic_managed_memory_impl + typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType, ipcdetail::managed_open_or_create_impl <ipcdetail::file_wrapper, AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset @@ -61,7 +61,7 @@ class basic_managed_mapped_file private: - typedef ipcdetail::create_open_func<base_t> create_open_func_t; + 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; @@ -75,16 +75,16 @@ class basic_managed_mapped_file public: //functions - //!Creates mapped file and creates and places the segment manager. + //!Creates mapped file and creates and places the segment manager. //!This can throw. basic_managed_mapped_file() {} - //!Creates mapped file and creates and places the segment manager. + //!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, size_type size, const void *addr = 0, const permissions &perm = permissions()) - : m_mfile(create_only, name, size, read_write, addr, + : m_mfile(create_only, name, size, read_write, addr, create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) {} @@ -93,39 +93,39 @@ class basic_managed_mapped_file //!segment. //!This can throw. basic_managed_mapped_file (open_or_create_t open_or_create, - const char *name, size_type size, + const char *name, size_type size, const void *addr = 0, const permissions &perm = permissions()) : m_mfile(open_or_create, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), + create_open_func_t(get_this_pointer(), ipcdetail::DoOpenOrCreate), perm) {} //!Connects to a created mapped file and its segment manager. //!This can throw. - basic_managed_mapped_file (open_only_t open_only, const char* name, + basic_managed_mapped_file (open_only_t open_only, const char* name, const void *addr = 0) : m_mfile(open_only, name, read_write, addr, - create_open_func_t(get_this_pointer(), + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} //!Connects to a created mapped file and its segment manager //!in copy_on_write mode. //!This can throw. - basic_managed_mapped_file (open_copy_on_write_t, const char* name, + basic_managed_mapped_file (open_copy_on_write_t, const char* name, const void *addr = 0) - : m_mfile(open_only, name, copy_on_write, addr, - create_open_func_t(get_this_pointer(), + : m_mfile(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} //!Connects to a created mapped file and its segment manager //!in read-only mode. //!This can throw. - basic_managed_mapped_file (open_read_only_t, const char* name, + basic_managed_mapped_file (open_read_only_t, const char* name, const void *addr = 0) - : m_mfile(open_only, name, read_only, addr, - create_open_func_t(get_this_pointer(), + : m_mfile(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} @@ -167,8 +167,8 @@ class basic_managed_mapped_file bool flush() { return m_mfile.flush(); } - //!Tries to resize mapped file so that we have room for - //!more objects. + //!Tries to resize mapped file so that we have room for + //!more objects. //! //!This function is not synchronized so no other thread or process should //!be reading or writing the file diff --git a/boost/interprocess/managed_shared_memory.hpp b/boost/interprocess/managed_shared_memory.hpp index cec9591be4..0f74c1a0b9 100644 --- a/boost/interprocess/managed_shared_memory.hpp +++ b/boost/interprocess/managed_shared_memory.hpp @@ -25,23 +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 { -//!A basic shared memory named object creation class. Initializes the -//!shared memory segment. Inherits all basic functionality from +//!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>*/ template < - class CharType, - class AllocationAlgorithm, + class CharType, + class AllocationAlgorithm, template<class IndexConfig> class IndexType > -class basic_managed_shared_memory +class basic_managed_shared_memory : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType ,ipcdetail::managed_open_or_create_impl<shared_memory_object @@ -50,7 +50,7 @@ class basic_managed_shared_memory , AllocationAlgorithm::Alignment> { /// @cond - typedef ipcdetail::basic_managed_memory_impl + typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType, ipcdetail::managed_open_or_create_impl < shared_memory_object, AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset> base_t; @@ -87,12 +87,12 @@ class basic_managed_shared_memory basic_managed_shared_memory() {} - //!Creates shared memory and creates and places the segment manager. + //!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, size_type size, const void *addr = 0, const permissions& perm = permissions()) : base_t() - , base2_t(create_only, name, size, read_write, addr, + , base2_t(create_only, name, size, read_write, addr, create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) {} @@ -101,43 +101,43 @@ class basic_managed_shared_memory //!segment. //!This can throw. basic_managed_shared_memory (open_or_create_t open_or_create, - const char *name, size_type size, + const char *name, size_type size, const void *addr = 0, const permissions& perm = permissions()) : base_t() - , base2_t(open_or_create, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), + , base2_t(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpenOrCreate), perm) {} //!Connects to a created shared memory and its segment manager. //!in copy_on_write mode. //!This can throw. - basic_managed_shared_memory (open_copy_on_write_t, const char* name, + basic_managed_shared_memory (open_copy_on_write_t, const char* name, const void *addr = 0) : base_t() - , base2_t(open_only, name, copy_on_write, addr, - create_open_func_t(get_this_pointer(), + , base2_t(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} //!Connects to a created shared memory and its segment manager. //!in read-only mode. //!This can throw. - basic_managed_shared_memory (open_read_only_t, const char* name, + basic_managed_shared_memory (open_read_only_t, const char* name, const void *addr = 0) : base_t() - , base2_t(open_only, name, read_only, addr, - create_open_func_t(get_this_pointer(), + , base2_t(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} //!Connects to a created shared memory and its segment manager. //!This can throw. - basic_managed_shared_memory (open_only_t open_only, const char* name, + basic_managed_shared_memory (open_only_t open_only, const char* name, const void *addr = 0) : base_t() - , base2_t(open_only, name, read_write, addr, - create_open_func_t(get_this_pointer(), + , base2_t(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} @@ -168,7 +168,7 @@ class basic_managed_shared_memory } //!Tries to resize the managed shared memory object so that we have - //!room for more objects. + //!room for more objects. //! //!This function is not synchronized so no other thread or process should //!be reading or writing the file @@ -187,12 +187,6 @@ class basic_managed_shared_memory return base_t::template shrink_to_fit <basic_managed_shared_memory>(shmname); } - - bool flush() - { - return this->base2_t::flush(); - } - /// @cond //!Tries to find a previous named allocation address. Returns a memory diff --git a/boost/interprocess/managed_windows_shared_memory.hpp b/boost/interprocess/managed_windows_shared_memory.hpp index 959194cc19..414007a614 100644 --- a/boost/interprocess/managed_windows_shared_memory.hpp +++ b/boost/interprocess/managed_windows_shared_memory.hpp @@ -25,15 +25,15 @@ #include <boost/move/move.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 { -//!A basic managed windows shared memory creation class. Initializes the -//!shared memory segment. Inherits all basic functionality from +//!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> //!Unlike basic_managed_shared_memory, it has //!no kernel persistence and the shared memory is destroyed @@ -45,11 +45,11 @@ namespace interprocess { //!basic_managed_shared_memory can't communicate between them. template < - class CharType, - class AllocationAlgorithm, + class CharType, + class AllocationAlgorithm, template<class IndexConfig> class IndexType > -class basic_managed_windows_shared_memory +class basic_managed_windows_shared_memory : public ipcdetail::basic_managed_memory_impl < CharType, AllocationAlgorithm, IndexType , ipcdetail::managed_open_or_create_impl @@ -60,7 +60,7 @@ class basic_managed_windows_shared_memory { /// @cond private: - typedef ipcdetail::basic_managed_memory_impl + typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType, ipcdetail::managed_open_or_create_impl <windows_shared_memory, AllocationAlgorithm::Alignment, false>::ManagedOpenOrCreateUserOffset> base_t; @@ -82,12 +82,12 @@ class basic_managed_windows_shared_memory basic_managed_windows_shared_memory() {} - //!Creates shared memory and creates and places the segment manager. + //!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, size_type size, const void *addr = 0, const permissions &perm = permissions()) - : m_wshm(create_only, name, size, read_write, addr, + : m_wshm(create_only, name, size, read_write, addr, create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) {} @@ -97,11 +97,11 @@ class basic_managed_windows_shared_memory //!This can throw. basic_managed_windows_shared_memory (open_or_create_t open_or_create, - const char *name, size_type size, + const char *name, size_type size, const void *addr = 0, const permissions &perm = permissions()) - : m_wshm(open_or_create, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), + : m_wshm(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpenOrCreate), perm) {} @@ -109,8 +109,8 @@ class basic_managed_windows_shared_memory //!This can throw. basic_managed_windows_shared_memory (open_only_t open_only, const char* name, const void *addr = 0) - : m_wshm(open_only, name, read_write, addr, - create_open_func_t(get_this_pointer(), + : m_wshm(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} @@ -119,7 +119,7 @@ class basic_managed_windows_shared_memory //!This can throw. basic_managed_windows_shared_memory (open_copy_on_write_t, const char* name, const void *addr = 0) - : m_wshm(open_only, name, copy_on_write, addr, + : m_wshm(open_only, name, copy_on_write, addr, create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} @@ -129,7 +129,7 @@ class basic_managed_windows_shared_memory basic_managed_windows_shared_memory (open_read_only_t, const char* name, const void *addr = 0) : base_t() - , m_wshm(open_only, name, read_only, addr, + , m_wshm(open_only, name, read_only, addr, create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} diff --git a/boost/interprocess/managed_xsi_shared_memory.hpp b/boost/interprocess/managed_xsi_shared_memory.hpp index 9601920254..dc909f6824 100644 --- a/boost/interprocess/managed_xsi_shared_memory.hpp +++ b/boost/interprocess/managed_xsi_shared_memory.hpp @@ -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,16 +36,16 @@ namespace boost { namespace interprocess { -//!A basic X/Open System Interface (XSI) shared memory named object creation class. Initializes the -//!shared memory segment. Inherits all basic functionality from +//!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>*/ template < - class CharType, - class AllocationAlgorithm, + class CharType, + class AllocationAlgorithm, template<class IndexConfig> class IndexType > -class basic_managed_xsi_shared_memory +class basic_managed_xsi_shared_memory : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType ,ipcdetail::managed_open_or_create_impl @@ -61,7 +61,7 @@ class basic_managed_xsi_shared_memory public: typedef ipcdetail::managed_open_or_create_impl <xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment, false, true> base2_t; - typedef ipcdetail::basic_managed_memory_impl + typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType, base2_t::ManagedOpenOrCreateUserOffset> base_t; @@ -92,12 +92,12 @@ class basic_managed_xsi_shared_memory basic_managed_xsi_shared_memory() {} - //!Creates shared memory and creates and places the segment manager. + //!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, std::size_t size, const void *addr = 0, const permissions& perm = permissions()) : base_t() - , base2_t(create_only, key, size, read_write, addr, + , base2_t(create_only, key, size, read_write, addr, create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) {} @@ -106,32 +106,32 @@ class basic_managed_xsi_shared_memory //!segment. //!This can throw. basic_managed_xsi_shared_memory (open_or_create_t open_or_create, - const xsi_key &key, std::size_t size, + const xsi_key &key, std::size_t size, const void *addr = 0, const permissions& perm = permissions()) : base_t() - , base2_t(open_or_create, key, size, read_write, addr, - create_open_func_t(get_this_pointer(), + , base2_t(open_or_create, key, size, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpenOrCreate), perm) {} //!Connects to a created shared memory and its segment manager. //!in read-only mode. //!This can throw. - basic_managed_xsi_shared_memory (open_read_only_t, const xsi_key &key, + basic_managed_xsi_shared_memory (open_read_only_t, const xsi_key &key, const void *addr = 0) : base_t() - , base2_t(open_only, key, read_only, addr, - create_open_func_t(get_this_pointer(), + , base2_t(open_only, key, read_only, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} //!Connects to a created shared memory and its segment manager. //!This can throw. - basic_managed_xsi_shared_memory (open_only_t open_only, const xsi_key &key, + basic_managed_xsi_shared_memory (open_only_t open_only, const xsi_key &key, const void *addr = 0) : base_t() - , base2_t(open_only, key, read_write, addr, - create_open_func_t(get_this_pointer(), + , base2_t(open_only, key, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} diff --git a/boost/interprocess/mapped_region.hpp b/boost/interprocess/mapped_region.hpp index eae3f36220..522c1e403a 100644 --- a/boost/interprocess/mapped_region.hpp +++ b/boost/interprocess/mapped_region.hpp @@ -20,10 +20,11 @@ #include <boost/interprocess/detail/utilities.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> #include <string> -#include <limits> +#include <boost/cstdint.hpp> -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) # include <boost/interprocess/detail/win32_api.hpp> +# include <boost/interprocess/sync/windows/sync_utils.hpp> #else # ifdef BOOST_HAS_UNISTD_H # include <fcntl.h> @@ -55,6 +56,10 @@ namespace ipcdetail{ class raw_mapped_region_creator; } //!The mapped_region class represents a portion or region created from a //!memory_mappable object. +//! +//!The OS can map a region bigger than the requested one, as region must +//!be multiple of the page size, but mapped_region will always refer to +//!the region specified by the user. class mapped_region { /// @cond @@ -65,9 +70,15 @@ class mapped_region public: //!Creates a mapping region of the mapped memory "mapping", starting in - //!offset "offset", and the mapping's size will be "size". The mapping - //!can be opened for read-only "read_only" or read-write - //!"read_write. + //!offset "offset", and the mapping's size will be "size". The mapping + //!can be opened for read only, read-write or copy-on-write. + //! + //!If an address is specified, both the offset and the address must be + //!multiples of the page size. + //! + //!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. template<class MemoryMappable> mapped_region(const MemoryMappable& mapping ,mode_t mode @@ -75,8 +86,8 @@ class mapped_region ,std::size_t size = 0 ,const void *address = 0); - //!Default constructor. Default constructor. Address will be 0 (nullptr). - //!Size and offset will be 0. + //!Default constructor. Address will be 0 (nullptr). + //!Size will be 0. //!Does not throw mapped_region(); @@ -84,12 +95,12 @@ class mapped_region //!region and "other" will be left in default constructor state. mapped_region(BOOST_RV_REF(mapped_region) other) #if defined (BOOST_INTERPROCESS_WINDOWS) - : m_base(0), m_size(0), m_offset(0) - , m_extra_offset(0) + : m_base(0), m_size(0) + , m_page_offset(0) , m_mode(read_only) - , m_file_mapping_hnd(ipcdetail::invalid_file()) + , m_file_or_mapping_hnd(ipcdetail::invalid_file()) #else - : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only), m_is_xsi(false) + : m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false) #endif { this->swap(other); } @@ -106,33 +117,31 @@ class mapped_region return *this; } - //!Returns the size of the mapping. Note for windows users: If - //!windows_shared_memory is mapped using 0 as the size, it returns 0 - //!because the size is unknown. Never throws. + //!Returns the size of the mapping. Never throws. std::size_t get_size() const; //!Returns the base address of the mapping. //!Never throws. void* get_address() const; - //!Returns the offset of the mapping from the beginning of the - //!mapped memory. Never throws. - offset_t get_offset() const; - - //!Returns the mode of the mapping used to construct the mapped file. + //!Returns the mode of the mapping used to construct the mapped region. //!Never throws. mode_t get_mode() const; - //!Flushes to the disk a byte range within the mapped memory. - //!Never throws - bool flush(std::size_t mapping_offset = 0, std::size_t numbytes = 0); + //!Flushes to the disk a byte range within the mapped memory. + //!If 'async' is true, the function will return before flushing operation is completed + //!If 'async' is false, function will return once data has been written into the underlying + //!device (i.e., in mapped files OS cached information is written to disk). + //!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); //!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. + //!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 @@ -140,6 +149,13 @@ class mapped_region //!Closes a previously opened memory mapping. Never throws void priv_close(); + 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; + 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); + template<int dummy> struct page_size_holder { @@ -149,11 +165,10 @@ class mapped_region void* m_base; std::size_t m_size; - offset_t m_offset; - offset_t m_extra_offset; + std::size_t m_page_offset; mode_t m_mode; - #if (defined BOOST_INTERPROCESS_WINDOWS) - file_handle_t m_file_mapping_hnd; + #if defined(BOOST_INTERPROCESS_WINDOWS) + file_handle_t m_file_or_mapping_hnd; #else bool m_is_xsi; #endif @@ -161,6 +176,10 @@ class mapped_region friend class ipcdetail::interprocess_tester; friend class ipcdetail::raw_mapped_region_creator; void dont_close_on_destruction(); + #if defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) + template<int Dummy> + static void destroy_syncs_in_range(const void *addr, std::size_t size); + #endif /// @endcond }; @@ -175,20 +194,74 @@ inline mapped_region::~mapped_region() inline std::size_t mapped_region::get_size() const { return m_size; } -inline offset_t mapped_region::get_offset() const -{ return m_offset; } - inline mode_t mapped_region::get_mode() const { return m_mode; } inline void* mapped_region::get_address() const { return m_base; } +inline void* mapped_region::priv_map_address() const +{ return static_cast<char*>(m_base) - m_page_offset; } + +inline std::size_t mapped_region::priv_map_size() const +{ return m_size + m_page_offset; } + +inline bool mapped_region::priv_flush_param_check + (std::size_t mapping_offset, void *&addr, std::size_t &numbytes) const +{ + //Check some errors + if(m_base == 0) + return false; + + if(mapping_offset >= m_size || (mapping_offset + numbytes) > m_size){ + return false; + } + + //Update flush size if the user does not provide it + if(numbytes == 0){ + numbytes = m_size - mapping_offset; + } + addr = (char*)this->priv_map_address() + mapping_offset; + numbytes += m_page_offset; + 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) +{ + //Check if mapping size fits in the user address space + //as offset_t is the maximum file size and its signed. + if(mapping_size < offset || + boost::uintmax_t(mapping_size - (offset - page_offset)) > + boost::uintmax_t(std::size_t(-1))){ + error_info err(size_error); + throw interprocess_exception(err); + } + size = static_cast<std::size_t>(mapping_size - (offset - page_offset)); +} + +inline offset_t mapped_region::priv_page_offset_addr_fixup(offset_t offset, const void *&address) +{ + //We can't map any offset so we have to obtain system's + //memory granularity + const std::size_t page_size = mapped_region::get_page_size(); + + //We calculate the difference between demanded and valid offset + //(always less than a page in std::size_t, thus, representable by std::size_t) + const std::size_t page_offset = + static_cast<std::size_t>(offset - (offset / page_size) * page_size); + //Update the mapping address + if(address){ + address = static_cast<const char*>(address) - page_offset; + } + return page_offset; +} + #if defined (BOOST_INTERPROCESS_WINDOWS) inline mapped_region::mapped_region() - : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only) - , m_file_mapping_hnd(ipcdetail::invalid_file()) + : m_base(0), m_size(0), m_page_offset(0), m_mode(read_only) + , m_file_or_mapping_hnd(ipcdetail::invalid_file()) {} template<int dummy> @@ -206,169 +279,146 @@ inline mapped_region::mapped_region ,offset_t offset ,std::size_t size ,const void *address) - : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(mode) - , m_file_mapping_hnd(ipcdetail::invalid_file()) + : m_base(0), m_size(0), m_page_offset(0), m_mode(mode) + , m_file_or_mapping_hnd(ipcdetail::invalid_file()) { mapping_handle_t mhandle = mapping.get_mapping_handle(); - file_handle_t native_mapping_handle = 0; - - //Set accesses - unsigned long file_map_access = 0; - unsigned long map_access = 0; - - switch(mode) { - case read_only: - case read_private: - file_map_access |= winapi::page_readonly; - map_access |= winapi::file_map_read; - break; - case read_write: - file_map_access |= winapi::page_readwrite; - map_access |= winapi::file_map_write; - break; - case copy_on_write: - file_map_access |= winapi::page_writecopy; - map_access |= winapi::file_map_copy; - break; - default: - { - error_info err(mode_error); - throw interprocess_exception(err); - } - break; - } - - if(!mhandle.is_shm){ - //Update mapping size if the user does not specify it - if(size == 0){ - __int64 total_size; - if(!winapi::get_file_size - (ipcdetail::file_handle_from_mapping_handle - (mapping.get_mapping_handle()), total_size)){ - error_info err(winapi::get_last_error()); - throw interprocess_exception(err); - } + file_handle_t native_mapping_handle = 0; + + //Set accesses + //For "create_file_mapping" + unsigned long protection = 0; + //For "mapviewoffile" + unsigned long map_access = 0; + + switch(mode) + { + case read_only: + case read_private: + protection |= winapi::page_readonly; + map_access |= winapi::file_map_read; + break; + case read_write: + protection |= winapi::page_readwrite; + map_access |= winapi::file_map_write; + break; + case copy_on_write: + protection |= winapi::page_writecopy; + map_access |= winapi::file_map_copy; + break; + default: + { + error_info err(mode_error); + throw interprocess_exception(err); + } + break; + } - if(static_cast<unsigned __int64>(total_size) > - (std::numeric_limits<std::size_t>::max)()){ - error_info err(size_error); + //For file mapping (including emulated shared memory through temporary files), + //the device is a file handle so we need to obtain file's size and call create_file_mapping + //to obtain the mapping handle. + //For files we don't need the file mapping after mapping the memory, as the file is there + //so we'll program the handle close + void * handle_to_close = winapi::invalid_handle_value; + if(!mhandle.is_shm){ + //Create mapping handle + native_mapping_handle = winapi::create_file_mapping + ( ipcdetail::file_handle_from_mapping_handle(mapping.get_mapping_handle()) + , protection, 0, 0, 0); + + //Check if all is correct + if(!native_mapping_handle){ + error_info err = winapi::get_last_error(); throw interprocess_exception(err); } - size = static_cast<std::size_t>(total_size - offset); + handle_to_close = native_mapping_handle; } - - //Create file mapping - native_mapping_handle = - winapi::create_file_mapping - (ipcdetail::file_handle_from_mapping_handle(mapping.get_mapping_handle()), file_map_access, 0, 0, 0, 0); - - //Check if all is correct - if(!native_mapping_handle){ - error_info err = winapi::get_last_error(); - this->priv_close(); - throw interprocess_exception(err); + else{ + //For windows_shared_memory the device handle is already a mapping handle + //and we need to maintain it + native_mapping_handle = mhandle.handle; } - } + //RAII handle close on scope exit + const winapi::handle_closer close_handle(handle_to_close); + (void)close_handle; - //We can't map any offset so we have to obtain system's - //memory granularity - unsigned long granularity = 0; - unsigned long foffset_low; - unsigned long foffset_high; + const offset_t page_offset = priv_page_offset_addr_fixup(offset, address); - winapi::system_info info; - get_system_info(&info); - granularity = info.dwAllocationGranularity; - - //Now we calculate valid offsets - foffset_low = (unsigned long)(offset / granularity) * granularity; - foffset_high = (unsigned long)(((offset / granularity) * granularity) >> 32); - - //We calculate the difference between demanded and valid offset - m_extra_offset = (offset - (offset / granularity) * granularity); - - //Store user values in memory - m_offset = offset; - m_size = size; + //Obtain mapping size if user provides 0 size + if(size == 0){ + offset_t mapping_size; + if(!winapi::get_file_mapping_size(native_mapping_handle, mapping_size)){ + error_info err = winapi::get_last_error(); + throw interprocess_exception(err); + } + //This can throw + priv_size_from_mapping_size(mapping_size, offset, page_offset, size); + } - //Update the mapping address - if(address){ - address = static_cast<const char*>(address) - m_extra_offset; - } - if(mhandle.is_shm){ - //Windows shared memory needs the duplication of the handle if we want to - //make mapped_region independent from the mappable device - if(!winapi::duplicate_current_process_handle(mhandle.handle, &m_file_mapping_hnd)){ + //Map with new offsets and size + void *base = winapi::map_view_of_file_ex + (native_mapping_handle, + map_access, + offset - page_offset, + static_cast<std::size_t>(page_offset + size), + const_cast<void*>(address)); + //Check error + if(!base){ error_info err = winapi::get_last_error(); - this->priv_close(); throw interprocess_exception(err); } - native_mapping_handle = m_file_mapping_hnd; - } - //Map with new offsets and size - m_base = winapi::map_view_of_file_ex - (native_mapping_handle, - map_access, - foffset_high, - foffset_low, - m_size ? static_cast<std::size_t>(m_extra_offset + m_size) : 0, - const_cast<void*>(address)); - - if(!mhandle.is_shm){ - //For files we don't need the file mapping anymore - winapi::close_handle(native_mapping_handle); + //Calculate new base for the user + m_base = static_cast<char*>(base) + page_offset; + m_page_offset = page_offset; + m_size = size; } - - //Check error - if(!m_base){ + //Windows shared memory needs the duplication of the handle if we want to + //make mapped_region independent from the mappable device + // + //For mapped files, we duplicate the file handle to be able to FlushFileBuffers + if(!winapi::duplicate_current_process_handle(mhandle.handle, &m_file_or_mapping_hnd)){ error_info err = winapi::get_last_error(); this->priv_close(); throw interprocess_exception(err); } - - //Calculate new base for the user - m_base = static_cast<char*>(m_base) + m_extra_offset; } -inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes) +inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes, bool async) { - //Check some errors - if(m_base == 0) + void *addr; + if(!this->priv_flush_param_check(mapping_offset, addr, numbytes)){ return false; - - if(mapping_offset >= m_size || (mapping_offset + numbytes) > m_size){ + } + //Flush it all + if(!winapi::flush_view_of_file(addr, numbytes)){ return false; } - - //Update flush size if the user does not provide it - if(m_size == 0){ - numbytes = 0; + //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 && + winapi::get_file_type(m_file_or_mapping_hnd) == winapi::file_type_disk){ + return winapi::flush_file_buffers(m_file_or_mapping_hnd); } - else if(numbytes == 0){ - numbytes = m_size - mapping_offset; - } - - //Flush it all - return winapi::flush_view_of_file - (static_cast<char*>(m_base)+mapping_offset, - static_cast<std::size_t>(numbytes)); + return true; } inline void mapped_region::priv_close() { if(m_base){ - winapi::unmap_view_of_file(static_cast<char*>(m_base) - m_extra_offset); + void *addr = this->priv_map_address(); + #if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) + mapped_region::destroy_syncs_in_range<0>(addr, m_size); + #endif + winapi::unmap_view_of_file(addr); m_base = 0; } - #if (defined BOOST_INTERPROCESS_WINDOWS) - if(m_file_mapping_hnd != ipcdetail::invalid_file()){ - winapi::close_handle(m_file_mapping_hnd); - m_file_mapping_hnd = ipcdetail::invalid_file(); - } - #endif + if(m_file_or_mapping_hnd != ipcdetail::invalid_file()){ + winapi::close_handle(m_file_or_mapping_hnd); + m_file_or_mapping_hnd = ipcdetail::invalid_file(); + } } inline void mapped_region::dont_close_on_destruction() @@ -377,7 +427,7 @@ inline void mapped_region::dont_close_on_destruction() #else //#if (defined BOOST_INTERPROCESS_WINDOWS) inline mapped_region::mapped_region() - : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only), m_is_xsi(false) + : m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false) {} template<int dummy> @@ -391,7 +441,7 @@ inline mapped_region::mapped_region , offset_t offset , std::size_t size , const void *address) - : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(mode), m_is_xsi(false) + : 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(); @@ -430,28 +480,25 @@ inline mapped_region::mapped_region } //Update members m_base = base; - m_offset = offset; m_size = size; m_mode = mode; - m_extra_offset = 0; + m_page_offset = 0; m_is_xsi = true; return; } #endif //ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + + //We calculate the difference between demanded and valid offset + const offset_t page_offset = priv_page_offset_addr_fixup(offset, address); + if(size == 0){ struct ::stat buf; if(0 != fstat(map_hnd.handle, &buf)){ error_info err(system_error_code()); throw interprocess_exception(err); } - std::size_t filesize = (std::size_t)buf.st_size; - if((std::size_t)offset >= filesize){ - error_info err(size_error); - throw interprocess_exception(err); - } - - filesize -= offset; - size = filesize; + //This can throw + priv_size_from_mapping_size(buf.st_size, offset, page_offset, size); } //Create new mapping @@ -488,35 +535,23 @@ inline mapped_region::mapped_region break; } - //We calculate the difference between demanded and valid offset - const std::size_t page_size = this->get_page_size(); - const offset_t extra_offset = offset - (offset / page_size) * page_size; - - - //Update the mapping address - if(address){ - address = static_cast<const char*>(address) - extra_offset; - } - //Map it to the address space void* base = mmap ( const_cast<void*>(address) - , static_cast<std::size_t>(extra_offset + size) + , static_cast<std::size_t>(page_offset + size) , prot , flags , mapping.get_mapping_handle().handle - , offset - extra_offset); + , offset - page_offset); //Check if mapping was successful if(base == MAP_FAILED){ error_info err = system_error_code(); - this->priv_close(); throw interprocess_exception(err); } //Calculate new base for the user - m_base = static_cast<char*>(base) + extra_offset; - m_extra_offset = extra_offset; - m_offset = offset; + m_base = static_cast<char*>(base) + page_offset; + m_page_offset = page_offset; m_size = size; //Check for fixed mapping error @@ -527,17 +562,14 @@ inline mapped_region::mapped_region } } -inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes) +inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes, bool async) { - if(mapping_offset >= m_size || (mapping_offset+numbytes)> m_size){ + void *addr; + if(!this->priv_flush_param_check(mapping_offset, addr, numbytes)){ return false; } - - if(numbytes == 0){ - numbytes = m_size - mapping_offset; - } //Flush it all - return msync(static_cast<char*>(m_base)+mapping_offset, numbytes, MS_ASYNC) == 0; + return msync( addr, numbytes, async ? MS_ASYNC : MS_SYNC) == 0; } inline void mapped_region::priv_close() @@ -551,7 +583,7 @@ inline void mapped_region::priv_close() return; } #endif //#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS - munmap(static_cast<char*>(m_base) - m_extra_offset, m_size + m_extra_offset); + munmap(this->priv_map_address(), this->priv_map_size()); m_base = 0; } } @@ -577,11 +609,10 @@ inline void mapped_region::swap(mapped_region &other) { ipcdetail::do_swap(this->m_base, other.m_base); ipcdetail::do_swap(this->m_size, other.m_size); - ipcdetail::do_swap(this->m_offset, other.m_offset); - ipcdetail::do_swap(this->m_extra_offset, other.m_extra_offset); + 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) - ipcdetail::do_swap(this->m_file_mapping_hnd, other.m_file_mapping_hnd); + 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); #endif @@ -603,3 +634,32 @@ struct null_mapped_region_function #endif //BOOST_INTERPROCESS_MAPPED_REGION_HPP +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#ifndef BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP +#define BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP + +#if defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) +# include <boost/interprocess/sync/windows/sync_utils.hpp> +# include <boost/interprocess/detail/windows_intermodule_singleton.hpp> + +namespace boost { +namespace interprocess { + +template<int Dummy> +inline void mapped_region::destroy_syncs_in_range(const void *addr, std::size_t size) +{ + ipcdetail::sync_handles &handles = + ipcdetail::windows_intermodule_singleton<ipcdetail::sync_handles>::get(); + handles.destroy_syncs_in_range(addr, size); +} + +} //namespace interprocess { +} //namespace boost { + +#endif //defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) + +#endif //#ifdef BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP + +#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + diff --git a/boost/interprocess/mem_algo/detail/mem_algo_common.hpp b/boost/interprocess/mem_algo/detail/mem_algo_common.hpp index d609f46aee..91d798145b 100644 --- a/boost/interprocess/mem_algo/detail/mem_algo_common.hpp +++ b/boost/interprocess/mem_algo/detail/mem_algo_common.hpp @@ -117,7 +117,7 @@ class memory_algorithm_common lcm_val = max; //If we want to use minbytes data to get a buffer between maxbytes - //and minbytes if maxbytes can't be achieved, calculate the + //and minbytes if maxbytes can't be achieved, calculate the //biggest of all possibilities current_forward = get_truncated_size_po2(received_size, backwards_multiple); needs_backwards = size_to_achieve - current_forward; @@ -176,7 +176,7 @@ class memory_algorithm_common lcm_val = lcm(max, min); } //If we want to use minbytes data to get a buffer between maxbytes - //and minbytes if maxbytes can't be achieved, calculate the + //and minbytes if maxbytes can't be achieved, calculate the //biggest of all possibilities current_forward = get_truncated_size(received_size, backwards_multiple); needs_backwards = size_to_achieve - current_forward; @@ -199,7 +199,7 @@ class memory_algorithm_common 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 +215,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 @@ -223,13 +223,13 @@ class memory_algorithm_common //Since we will split that block, we must request a bit more memory //if the alignment is near the beginning of the buffer, because otherwise, //there is no space for a new block before the alignment. - // + // // ____ Aligned here // | // ----------------------------------------------------- - // | MBU | + // | MBU | // ----------------------------------------------------- - size_type request = + size_type request = minimum_allocation + (2*MinBlockUnits*Alignment - AllocatedCtrlBytes //prevsize - UsableByPreviousChunk ); @@ -263,7 +263,7 @@ class memory_algorithm_common } //Buffer not aligned, find the aligned part. - // + // // ____ Aligned here // | // ----------------------------------------------------- @@ -324,7 +324,7 @@ class memory_algorithm_common return memory_algo->priv_get_user_buffer(second); } - static bool try_shrink + static bool try_shrink (MemoryAlgorithm *memory_algo, void *ptr ,const size_type max_size, const size_type preferred_size ,size_type &received_size) @@ -361,8 +361,8 @@ class memory_algorithm_common if(old_user_units == preferred_user_units) return true; - size_type shrunk_user_units = - ((BlockCtrlUnits - AllocatedCtrlUnits) > preferred_user_units) + size_type shrunk_user_units = + ((BlockCtrlUnits - AllocatedCtrlUnits) >= preferred_user_units) ? (BlockCtrlUnits - AllocatedCtrlUnits) : preferred_user_units; @@ -380,7 +380,7 @@ class memory_algorithm_common return true; } - static bool shrink + static bool shrink (MemoryAlgorithm *memory_algo, void *ptr ,const size_type max_size, const size_type preferred_size ,size_type &received_size) @@ -389,7 +389,7 @@ class memory_algorithm_common block_ctrl *block = memory_algo->priv_get_block(ptr); size_type old_block_units = (size_type)block->m_size; - if(!try_shrink + if(!try_shrink (memory_algo, ptr, max_size, preferred_size, received_size)){ return false; } @@ -479,7 +479,7 @@ class memory_algorithm_common //The last block should take all the remaining space if((low_idx + 1) == n_elements || - (total_used_units + elem_units + + (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)) @@ -528,7 +528,7 @@ class memory_algorithm_common //Sanity check BOOST_ASSERT(total_used_units == received_units); } - + if(low_idx != n_elements){ priv_deallocate_many(memory_algo, boost::move(chain)); } 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 378cd82fd5..c36916b72f 100644 --- a/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp +++ b/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp @@ -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; @@ -93,10 +93,10 @@ class simple_seq_fit_impl public: //!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; } @@ -126,7 +126,7 @@ class simple_seq_fit_impl typedef ipcdetail::memory_algorithm_common<simple_seq_fit_impl> algo_impl_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(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); @@ -197,12 +197,12 @@ class simple_seq_fit_impl template<class T> std::pair<T *, bool> allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size,size_type &received_size, + size_type preferred_size,size_type &received_size, T *reuse_ptr = 0); std::pair<void *, bool> raw_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 sizeof_object = 1); //!Returns the size of the buffer previously allocated pointed by ptr @@ -306,7 +306,7 @@ simple_seq_fit_impl<MutexFamily, VoidPointer> size_type uint_this = (std::size_t)this_ptr; size_type uint_aligned_this = uint_this/Alignment*Alignment; size_type this_disalignment = (uint_this - uint_aligned_this); - size_type block1_off = + size_type block1_off = ipcdetail::get_rounded_size(sizeof(simple_seq_fit_impl) + extra_hdr_bytes + this_disalignment, Alignment) - this_disalignment; algo_impl_t::assert_alignment(this_disalignment + block1_off); @@ -322,7 +322,7 @@ simple_seq_fit_impl<MutexFamily, VoidPointer> size_type uint_this = (std::size_t)this; size_type uint_aligned_this = uint_this/Alignment*Alignment; size_type this_disalignment = (uint_this - uint_aligned_this); - size_type old_end = + size_type old_end = ipcdetail::get_truncated_size(m_header.m_size + this_disalignment, Alignment) - this_disalignment; algo_impl_t::assert_alignment(old_end + this_disalignment); @@ -426,7 +426,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; @@ -463,7 +463,7 @@ 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) -{ +{ algo_impl_t::assert_alignment(addr); //Check size BOOST_ASSERT(!(size < MinBlockSize)); @@ -474,7 +474,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(priv_get_user_buffer(new_block)); } @@ -488,7 +488,7 @@ template<class MutexFamily, class VoidPointer> inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::size_type simple_seq_fit_impl<MutexFamily, VoidPointer>::get_free_memory() const { - return m_header.m_size - m_header.m_allocated - + return m_header.m_size - m_header.m_allocated - algo_impl_t::multiple_of_units(sizeof(*this) + m_header.m_extra_hdr_bytes); } @@ -523,7 +523,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,19 +583,19 @@ 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); //----------------------- return algo_impl_t:: - allocate_aligned(this, nbytes, alignment); + allocate_aligned(this, nbytes, alignment); } template<class MutexFamily, class VoidPointer> template<class T> inline std::pair<T*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: 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, T *reuse_ptr) { std::pair<void*, bool> ret = priv_allocation_command @@ -608,7 +608,7 @@ inline std::pair<T*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: template<class MutexFamily, class VoidPointer> inline std::pair<void*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects, - size_type preferred_objects,size_type &received_objects, + size_type preferred_objects,size_type &received_objects, void *reuse_ptr, size_type sizeof_object) { if(!sizeof_object) @@ -627,7 +627,7 @@ inline std::pair<void*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: template<class MutexFamily, class VoidPointer> inline std::pair<void*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: priv_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, size_type sizeof_object) { command &= ~boost::interprocess::expand_bwd; @@ -696,9 +696,9 @@ 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){ max_value(ipcdetail::get_rounded_size(min_size - extra_forward, Alignment) ,min_value(prev->get_user_bytes(), needs_backwards)); @@ -710,16 +710,16 @@ 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 = BlockCtrlUnits + (needs_backwards + extra_forward)/Alignment; - prev->m_size = + prev->m_size = (prev->get_total_bytes() - needs_backwards)/Alignment - BlockCtrlUnits; received_size = needs_backwards + extra_forward; m_header.m_allocated += needs_backwards + BlockCtrlBytes; @@ -775,7 +775,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 = algo_impl_t::shrink(this, reuse_ptr, limit_size, preferred_size, received_size); return std::pair<void *, bool> ((success ? reuse_ptr : 0), true); } @@ -885,7 +885,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>:: @@ -969,7 +969,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 +978,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 +992,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: BOOST_ASSERT(0); return false; } - return true; + return true; } template<class MutexFamily, class VoidPointer> inline @@ -1006,7 +1006,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 "units" //the second's size will be "block->m_size-units" size_type total_size = block->m_size; @@ -1057,7 +1057,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 * prev = &m_header.m_root; block_ctrl * pos = ipcdetail::to_raw_pointer(m_header.m_root.m_next); @@ -1071,9 +1071,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 @@ -1087,7 +1087,7 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr) //Try to combine with upper block char *block_char_ptr = reinterpret_cast<char*>(ipcdetail::to_raw_pointer(block)); - if ((block_char_ptr + Alignment*block->m_size) == + if ((block_char_ptr + Alignment*block->m_size) == reinterpret_cast<char*>(ipcdetail::to_raw_pointer(pos))){ block->m_size += pos->m_size; block->m_next = pos->m_next; @@ -1098,7 +1098,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) == block_char_ptr){ diff --git a/boost/interprocess/mem_algo/rbtree_best_fit.hpp b/boost/interprocess/mem_algo/rbtree_best_fit.hpp index f6f0c03a17..7ccc642e29 100644 --- a/boost/interprocess/mem_algo/rbtree_best_fit.hpp +++ b/boost/interprocess/mem_algo/rbtree_best_fit.hpp @@ -105,7 +105,7 @@ class rbtree_best_fit struct SizeHolder { - //!This block's memory size (including block_ctrl + //!This block's memory size (including block_ctrl //!header) in Alignment units size_type m_prev_size : sizeof(size_type)*CHAR_BIT; size_type m_size : sizeof(size_type)*CHAR_BIT - 2; @@ -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 @@ -157,13 +157,13 @@ 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 - //!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(rbtree_best_fit) //!offset that the allocator should not use at all. rbtree_best_fit (size_type size, size_type extra_hdr_bytes); @@ -238,12 +238,12 @@ class rbtree_best_fit template<class T> std::pair<T *, bool> allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size,size_type &received_size, + size_type preferred_size,size_type &received_size, T *reuse_ptr = 0); std::pair<void *, bool> raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_object, - size_type preferred_object,size_type &received_object, + size_type preferred_object,size_type &received_object, void *reuse_ptr = 0, size_type sizeof_object = 1); //!Returns the size of the buffer previously allocated pointed by ptr @@ -263,7 +263,7 @@ class rbtree_best_fit std::pair<void*, bool> priv_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, size_type sizeof_object); @@ -339,7 +339,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) @@ -370,7 +370,7 @@ class rbtree_best_fit /// @cond template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> -inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::size_type +inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::size_type rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment> ::priv_first_block_offset_from_this(const void *this_ptr, size_type extra_hdr_bytes) { @@ -386,7 +386,7 @@ 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) -{ +{ //Check alignment algo_impl_t::check_alignment(addr); //Check size @@ -398,16 +398,16 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: BOOST_ASSERT(first_big_block->m_size >= BlockCtrlUnits); //The "end" node is just a node of size 0 with the "end" bit set - block_ctrl *end_block = static_cast<block_ctrl*> + block_ctrl *end_block = static_cast<block_ctrl*> (new (reinterpret_cast<char*>(addr) + first_big_block->m_size*Alignment)SizeHolder); //This will overwrite the prev part of the "end" node priv_mark_as_free_block (first_big_block); #ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP - first_big_block->m_prev_size = end_block->m_size = + first_big_block->m_prev_size = end_block->m_size = (reinterpret_cast<char*>(first_big_block) - reinterpret_cast<char*>(end_block))/Alignment; #else - first_big_block->m_prev_size = end_block->m_size = + first_big_block->m_prev_size = end_block->m_size = (reinterpret_cast<char*>(end_block) - reinterpret_cast<char*>(first_big_block))/Alignment; #endif end_block->m_allocated = 1; @@ -444,7 +444,7 @@ inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_c { size_type block1_off = priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); const size_type original_first_block_size = m_header.m_size/Alignment*Alignment - block1_off/Alignment*Alignment - EndCtrlBlockBytes; - block_ctrl *end_block = reinterpret_cast<block_ctrl*> + block_ctrl *end_block = reinterpret_cast<block_ctrl*> (reinterpret_cast<char*>(this) + block1_off + original_first_block_size); return end_block; } @@ -479,7 +479,7 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::grow(size_type ext //Get the address of the first block block_ctrl *first_block = priv_first_block(); block_ctrl *old_end_block = priv_end_block(); - size_type old_border_offset = (size_type)(reinterpret_cast<char*>(old_end_block) - + size_type old_border_offset = (size_type)(reinterpret_cast<char*>(old_end_block) - reinterpret_cast<char*>(this)) + EndCtrlBlockBytes; //Update managed buffer's size @@ -500,10 +500,10 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::grow(size_type ext //between them new_end_block->m_allocated = 1; #ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP - new_end_block->m_size = (reinterpret_cast<char*>(first_block) - + new_end_block->m_size = (reinterpret_cast<char*>(first_block) - reinterpret_cast<char*>(new_end_block))/Alignment; #else - new_end_block->m_size = (reinterpret_cast<char*>(new_end_block) - + new_end_block->m_size = (reinterpret_cast<char*>(new_end_block) - reinterpret_cast<char*>(first_block))/Alignment; #endif first_block->m_prev_size = new_end_block->m_size; @@ -512,7 +512,7 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::grow(size_type ext //The old end block is the new block block_ctrl *new_block = old_end_block; - new_block->m_size = (reinterpret_cast<char*>(new_end_block) - + new_block->m_size = (reinterpret_cast<char*>(new_end_block) - reinterpret_cast<char*>(new_block))/Alignment; BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits); priv_mark_as_allocated_block(new_block); @@ -568,18 +568,18 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::shrink_to_fit() //Erase block from the free tree, since we will erase it m_header.m_imultiset.erase(Imultiset::s_iterator_to(*last_block)); - size_type shrunk_border_offset = (size_type)(reinterpret_cast<char*>(last_block) - + 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); //Write new end block attributes #ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP - new_end_block->m_size = first_block->m_prev_size = + new_end_block->m_size = first_block->m_prev_size = (reinterpret_cast<char*>(first_block) - reinterpret_cast<char*>(new_end_block))/Alignment; #else - new_end_block->m_size = first_block->m_prev_size = + new_end_block->m_size = first_block->m_prev_size = (reinterpret_cast<char*>(new_end_block) - reinterpret_cast<char*>(first_block))/Alignment; #endif @@ -604,7 +604,7 @@ template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::size_type rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::get_free_memory() const { - return m_header.m_size - m_header.m_allocated - + return m_header.m_size - m_header.m_allocated - priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); } @@ -614,7 +614,7 @@ rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: get_min_size (size_type extra_hdr_bytes) { return (algo_impl_t::ceil_units(sizeof(rbtree_best_fit)) + - algo_impl_t::ceil_units(extra_hdr_bytes) + + algo_impl_t::ceil_units(extra_hdr_bytes) + MinBlockUnits + EndCtrlBlockUnits)*Alignment; } @@ -625,13 +625,13 @@ inline bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: //----------------------- boost::interprocess::scoped_lock<mutex_type> guard(m_header); //----------------------- - size_type block1_off = + size_type block1_off = priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); - return m_header.m_allocated == 0 && + return m_header.m_allocated == 0 && m_header.m_imultiset.begin() != m_header.m_imultiset.end() && (++m_header.m_imultiset.begin()) == m_header.m_imultiset.end() - && m_header.m_imultiset.begin()->m_size == + && m_header.m_imultiset.begin()->m_size == (m_header.m_size - block1_off - EndCtrlBlockBytes)/Alignment; } @@ -659,7 +659,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: return false; } - size_type block1_off = + size_type block1_off = priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); //Check free bytes are less than size @@ -672,7 +672,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); //----------------------- @@ -684,18 +684,18 @@ inline void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> inline void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: allocate_aligned(size_type nbytes, size_type alignment) -{ +{ //----------------------- boost::interprocess::scoped_lock<mutex_type> guard(m_header); //----------------------- - return algo_impl_t::allocate_aligned(this, nbytes, alignment); + return algo_impl_t::allocate_aligned(this, nbytes, alignment); } template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> template<class T> inline std::pair<T*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: 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, T *reuse_ptr) { std::pair<void*, bool> ret = priv_allocation_command @@ -708,7 +708,7 @@ inline std::pair<T*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignmen template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> inline std::pair<void*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects, - size_type preferred_objects,size_type &received_objects, + size_type preferred_objects,size_type &received_objects, void *reuse_ptr, size_type sizeof_object) { if(!sizeof_object) @@ -728,7 +728,7 @@ inline std::pair<void*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlign template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> inline std::pair<void*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: priv_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, size_type sizeof_object) { std::pair<void*, bool> ret; @@ -815,7 +815,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: //Obtain the real size of the block block_ctrl *reuse = priv_get_block(reuse_ptr); - //Sanity check + //Sanity check //BOOST_ASSERT(reuse->m_size == priv_tail_size(reuse)); algo_impl_t::assert_alignment(reuse); @@ -859,12 +859,12 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: (reinterpret_cast<char*>(reuse) - needs_backwards_aligned); //Free old previous buffer - new_block->m_size = + new_block->m_size = AllocatedCtrlUnits + (needs_backwards_aligned + (received_size - UsableByPreviousChunk))/Alignment; BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits); priv_mark_as_allocated_block(new_block); - prev_block->m_size = (reinterpret_cast<char*>(new_block) - + prev_block->m_size = (reinterpret_cast<char*>(new_block) - reinterpret_cast<char*>(prev_block))/Alignment; BOOST_ASSERT(prev_block->m_size >= BlockCtrlUnits); priv_mark_as_free_block(prev_block); @@ -875,7 +875,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: { imultiset_iterator prev_block_it(Imultiset::s_iterator_to(*prev_block)); imultiset_iterator was_smaller_it(prev_block_it); - if(prev_block_it != m_header.m_imultiset.begin() && + if(prev_block_it != m_header.m_imultiset.begin() && (--(was_smaller_it = prev_block_it))->m_size > prev_block->m_size){ m_header.m_imultiset.erase(prev_block_it); m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *prev_block); @@ -884,7 +884,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); @@ -951,7 +951,7 @@ std::pair<void *, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>: //command &= (~boost::interprocess::expand_bwd); if(command & boost::interprocess::shrink_in_place){ - bool success = + bool success = algo_impl_t::shrink(this, reuse_ptr, limit_size, preferred_size, received_size); return std::pair<void *, bool> ((success ? reuse_ptr : 0), true); } @@ -1044,7 +1044,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) @@ -1084,7 +1084,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: //Check if we can split the next one in two parts if((merged_units - intended_units) >= BlockCtrlUnits){ - //This block is bigger than needed, split it in + //This block is bigger than needed, split it in //two blocks, the first one will be merged and //the second's size will be the remaining space BOOST_ASSERT(next_block->m_size == priv_next_block(next_block)->m_prev_size); @@ -1098,9 +1098,9 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: //overwrite the tree hook of the old next block. So we first erase the //old if needed and we'll insert the new one after creating the new next imultiset_iterator old_next_block_it(Imultiset::s_iterator_to(*next_block)); - const bool size_invariants_broken = + const bool size_invariants_broken = (next_block->m_size - rem_units ) < BlockCtrlUnits || - (old_next_block_it != m_header.m_imultiset.begin() && + (old_next_block_it != m_header.m_imultiset.begin() && (--imultiset_iterator(old_next_block_it))->m_size > rem_units); if(size_invariants_broken){ m_header.m_imultiset.erase(old_next_block_it); @@ -1267,7 +1267,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_check_and_al algo_impl_t::assert_alignment(block); 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 "units" and //the second's size "block->m_size-units" size_type block_old_size = block->m_size; @@ -1298,7 +1298,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,9 +1318,9 @@ 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 = + //volatile char *ptr = char *ptr = reinterpret_cast<char*>(block)+tree_hook_offset_in_block; const std::size_t s = BlockCtrlBytes - tree_hook_offset_in_block; std::memset(ptr, 0, s); @@ -1344,7 +1344,7 @@ 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)); diff --git a/boost/interprocess/mem_algo/simple_seq_fit.hpp b/boost/interprocess/mem_algo/simple_seq_fit.hpp index 5cc92c1103..1085ca00ac 100644 --- a/boost/interprocess/mem_algo/simple_seq_fit.hpp +++ b/boost/interprocess/mem_algo/simple_seq_fit.hpp @@ -31,7 +31,7 @@ namespace interprocess { //!This class implements the simple sequential fit algorithm with a simply //!linked list of free buffers. template<class MutexFamily, class VoidPointer> -class simple_seq_fit +class simple_seq_fit : public ipcdetail::simple_seq_fit_impl<MutexFamily, VoidPointer> { /// @cond @@ -41,7 +41,7 @@ class simple_seq_fit public: typedef typename base_t::size_type size_type; - //!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) //!offset that the allocator should not use at all.*/ simple_seq_fit (size_type size, size_type extra_hdr_bytes) diff --git a/boost/interprocess/offset_ptr.hpp b/boost/interprocess/offset_ptr.hpp index 4187543d57..ac8da2c292 100644 --- a/boost/interprocess/offset_ptr.hpp +++ b/boost/interprocess/offset_ptr.hpp @@ -82,19 +82,19 @@ class offset_ptr //!Never throws. template <class T> offset_ptr( T *ptr - , typename ipcdetail::enable_if< ipcdetail::is_convertible<T*, PointedType*> >::type * = 0) + , typename ipcdetail::enable_if< ipcdetail::is_convertible<T*, PointedType*> >::type * = 0) { this->set_offset(static_cast<PointedType*>(ptr)); } //!Constructor from other offset_ptr //!Never throws. - offset_ptr(const offset_ptr& ptr) + offset_ptr(const offset_ptr& ptr) { this->set_offset(ptr.get()); } - //!Constructor from other offset_ptr. If pointers of pointee types are + //!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) + , typename ipcdetail::enable_if< ipcdetail::is_convertible<T2*, PointedType*> >::type * = 0) { this->set_offset(static_cast<PointedType*>(ptr.get())); } //!Emulates static_cast operator. @@ -131,12 +131,12 @@ class offset_ptr //!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 + //!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; @@ -146,7 +146,7 @@ class offset_ptr //!Indexing operator. //!Never throws. template<class T> - reference operator[](T idx) const + reference operator[](T idx) const { return this->get()[idx]; } //!Assignment from pointer (saves extra conversion). @@ -159,13 +159,13 @@ class offset_ptr offset_ptr& operator= (const offset_ptr & pt) { pointer p(pt.get()); (void)p; this->set_offset(p); return *this; } - //!Assignment from related offset_ptr. If pointers of pointee types + //!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; } - + //!offset_ptr += difference_type. //!Never throws. offset_ptr &operator+= (difference_type offset) @@ -179,7 +179,7 @@ class offset_ptr //!++offset_ptr. //!Never throws. - offset_ptr& operator++ (void) + offset_ptr& operator++ (void) { this->inc_offset(sizeof (PointedType)); return *this; } //!offset_ptr++. @@ -189,7 +189,7 @@ class offset_ptr //!--offset_ptr. //!Never throws. - offset_ptr& operator-- (void) + offset_ptr& operator-- (void) { this->dec_offset(sizeof (PointedType)); return *this; } //!offset_ptr--. @@ -199,10 +199,10 @@ class offset_ptr //!safe bool conversion operator. //!Never throws. - operator unspecified_bool_type() const + operator unspecified_bool_type() const { return this->get()? &self_t::unspecified_bool_type_func : 0; } - //!Not operator. Not needed in theory, but improves portability. + //!Not operator. Not needed in theory, but improves portability. //!Never throws bool operator! () const { return this->get() == 0; } @@ -345,8 +345,8 @@ class offset_ptr #endif return static_cast<PointedType *>( static_cast<void*>( - (internal.m_offset == 1) ? - 0 : + (internal.m_offset == 1) ? + 0 : (const_cast<char*>(reinterpret_cast<const char*>(this)) + internal.m_offset) ) ); @@ -371,52 +371,52 @@ class offset_ptr //!operator<< //!for offset ptr -template<class E, class T, class W, class X, class Y, std::size_t Z> -inline std::basic_ostream<E, T> & operator<< +template<class E, class T, class W, class X, class Y, std::size_t Z> +inline std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, offset_ptr<W, X, Y, Z> const & p) { return os << p.get_offset(); } -//!operator>> +//!operator>> //!for offset ptr -template<class E, class T, class W, class X, class Y, std::size_t Z> -inline std::basic_istream<E, T> & operator>> +template<class E, class T, class W, class X, class Y, std::size_t Z> +inline std::basic_istream<E, T> & operator>> (std::basic_istream<E, T> & is, offset_ptr<W, X, Y, Z> & p) { return is >> p.get_offset(); } //!Simulation of static_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> +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> +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 { @@ -425,14 +425,14 @@ inline boost::interprocess::offset_ptr<T1, P1, O1, A1> //!has_trivial_constructor<> == true_type specialization for optimizations template <class T, class P, class O, std::size_t A> -struct has_trivial_constructor< boost::interprocess::offset_ptr<T, P, O, A> > +struct has_trivial_constructor< boost::interprocess::offset_ptr<T, P, O, A> > { static const bool value = true; }; ///has_trivial_destructor<> == true_type specialization for optimizations template <class T, class P, class O, std::size_t A> -struct has_trivial_destructor< boost::interprocess::offset_ptr<T, P, O, A> > +struct has_trivial_destructor< boost::interprocess::offset_ptr<T, P, O, A> > { static const bool value = true; }; @@ -440,7 +440,7 @@ struct has_trivial_destructor< boost::interprocess::offset_ptr<T, P, O, A> > //#if !defined(_MSC_VER) || (_MSC_VER >= 1400) namespace interprocess { //#endif -//!to_raw_pointer() enables boost::mem_fn to recognize offset_ptr. +//!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) @@ -482,7 +482,7 @@ struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits> typedef boost::interprocess::offset_ptr<T, P, O, A> pointer; //Bits are stored in the lower bits of the pointer except the LSB, //because this bit is used to represent the null pointer. - static const 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)); } diff --git a/boost/interprocess/segment_manager.hpp b/boost/interprocess/segment_manager.hpp index 4424695992..8680a953e2 100644 --- a/boost/interprocess/segment_manager.hpp +++ b/boost/interprocess/segment_manager.hpp @@ -69,9 +69,9 @@ class segment_manager_base typedef typename MemoryAlgorithm::void_pointer void_pointer; typedef typename MemoryAlgorithm::mutex_family mutex_family; typedef MemoryAlgorithm memory_algorithm; - + /// @cond - + //Experimental. Don't use typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain; typedef typename MemoryAlgorithm::difference_type difference_type; @@ -88,7 +88,7 @@ class segment_manager_base //!"size" is the size of the memory segment where //!the basic segment manager is being constructed. //! - //!"reserved_bytes" is the number of bytes + //!"reserved_bytes" is the number of bytes //!after the end of the memory algorithm object itself //!that the memory algorithm will exclude from //!dynamic allocation @@ -115,7 +115,7 @@ class segment_manager_base static size_type get_min_size (size_type size) { return MemoryAlgorithm::get_min_size(size); } - //!Allocates nbytes bytes. This function is only used in + //!Allocates nbytes bytes. This function is only used in //!single-segment management. Never throws void * allocate (size_type nbytes, std::nothrow_t) { return MemoryAlgorithm::allocate(nbytes); } @@ -165,22 +165,22 @@ class segment_manager_base //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc //!on failure void * allocate(size_type nbytes) - { + { void * ret = MemoryAlgorithm::allocate(nbytes); if(!ret) throw bad_alloc(); return ret; } - //!Allocates nbytes bytes. This function is only used in + //!Allocates nbytes bytes. This function is only used in //!single-segment management. Never throws void * allocate_aligned (size_type nbytes, size_type alignment, std::nothrow_t) { return MemoryAlgorithm::allocate_aligned(nbytes, alignment); } - //!Allocates nbytes bytes. This function is only used in + //!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(); @@ -269,7 +269,7 @@ class segment_manager_base throw bad_alloc(); } else{ - return 0; + return 0; } } @@ -293,7 +293,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); @@ -318,9 +318,9 @@ class segment_manager_base //!This object is placed in the beginning of memory segment and //!implements the allocation (named or anonymous) of portions //!of the segment. This object contains two indexes that -//!maintain an association between a name and a portion of the segment. +//!maintain an association between a name and a portion of the segment. //! -//!The first index contains the mappings for normal named objects using the +//!The first index contains the mappings for normal named objects using the //!char type specified in the template parameter. //! //!The second index contains the association for unique instances. The key will @@ -336,7 +336,7 @@ template<class CharType ,template<class IndexConfig> class IndexType> class segment_manager : public segment_manager_base<MemoryAlgorithm> -{ +{ /// @cond //Non-copyable segment_manager(); @@ -446,7 +446,7 @@ class segment_manager //!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,39 +466,39 @@ 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); } //!Returns no 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, std::nothrow_t) { return typename construct_iter_proxy<T>::type (this, name, true, false); } - //!Calls object function blocking recursive interprocess_mutex and guarantees that - //!no new named_alloc or destroy will be executed by any process while + //!Calls object function blocking recursive interprocess_mutex and guarantees that + //!no new named_alloc or destroy will be executed by any process while //!executing the object function call*/ template <class Func> void atomic_func(Func &f) @@ -571,22 +571,22 @@ class segment_manager static instance_type get_instance_type(const T *ptr) { return priv_get_instance_type(block_header_t::block_header_from_value(ptr)); } - //!Preallocates needed index resources to optimize the + //!Preallocates needed index resources to optimize the //!creation of "num" named objects in the managed memory segment. //!Can throw boost::interprocess::bad_alloc if there is no enough memory. void reserve_named_objects(size_type num) - { + { //------------------------------- scoped_lock<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 + //!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,32 +596,32 @@ 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 @@ -693,13 +693,13 @@ class segment_manager /// @cond - //!Generic named/anonymous new function. Offers all the possibilities, - //!such as throwing, search before creating, and the constructor is + //!Generic named/anonymous new function. Offers all the possibilities, + //!such as throwing, search before creating, and the constructor is //!encapsulated in an object function. template<class T> - T *generic_construct(const CharType *name, - size_type num, - bool try2find, + T *generic_construct(const CharType *name, + size_type num, + bool try2find, bool dothrow, ipcdetail::in_place_interface &table) { @@ -713,7 +713,7 @@ 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; @@ -737,13 +737,13 @@ class segment_manager { ipcdetail::placement_destroy<T> table; size_type size; - void *ret = priv_generic_find<char>(name, m_header.m_unique_index, table, size, is_intrusive_t(), lock); + void *ret = priv_generic_find<char>(name, m_header.m_unique_index, table, size, is_intrusive_t(), lock); return std::pair<T*, size_type>(static_cast<T*>(ret), size); } - void *priv_generic_construct(const CharType *name, - size_type num, - bool try2find, + void *priv_generic_construct(const CharType *name, + size_type num, + bool try2find, bool dothrow, ipcdetail::in_place_interface &table) { @@ -805,7 +805,7 @@ class segment_manager 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)); @@ -837,7 +837,7 @@ class segment_manager template <class CharT> void *priv_generic_find - (const CharT* name, + (const CharT* name, IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::in_place_interface &table, size_type &length, @@ -877,7 +877,7 @@ class segment_manager template <class CharT> void *priv_generic_find - (const CharT* name, + (const CharT* name, IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::in_place_interface &table, size_type &length, @@ -941,7 +941,7 @@ class segment_manager } template <class CharT> - bool priv_generic_named_destroy(const CharT *name, + 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) @@ -951,7 +951,7 @@ class segment_manager 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 +972,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()); @@ -992,7 +992,7 @@ class segment_manager } template <class CharT> - bool priv_generic_named_destroy(const CharT *name, + bool priv_generic_named_destroy(const CharT *name, IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::in_place_interface &table, ipcdetail::false_ is_intrusive_index) @@ -1006,7 +1006,7 @@ class segment_manager scoped_lock<rmutex> guard(m_header); //------------------------------- //Try to find the name in the index - index_it it = index.find(key_type (name, + index_it it = index.find(key_type (name, std::char_traits<CharT>::length(name))); //If not found, return false @@ -1033,7 +1033,7 @@ class segment_manager char *stored_name = static_cast<char*>(static_cast<void*>(const_cast<CharT*>(it->first.name()))); (void)stored_name; - //Check if the distance between the name pointer and the memory pointer + //Check if the distance between the name pointer and the memory pointer //is correct (this can detect incorrect type in destruction) std::size_t num = ctrl_data->m_value_bytes/table.size; void *values = ctrl_data->value(); @@ -1070,8 +1070,8 @@ class segment_manager template<class CharT> void * priv_generic_named_construct(unsigned char type, const CharT *name, - size_type num, - bool try2find, + size_type num, + bool try2find, bool dothrow, ipcdetail::in_place_interface &table, IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, @@ -1095,12 +1095,12 @@ class segment_manager //------------------------------- //Insert the node. This can throw. //First, we want to know if the key is already present before - //we allocate any memory, and if the key is not present, we + //we allocate any memory, and if the key is not present, we //want to allocate all memory in a single buffer that will //contain the name and the user buffer. // //Since equal_range(key) + insert(hint, value) approach is - //quite inefficient in container implementations + //quite inefficient in container implementations //(they re-test if the position is correct), I've chosen //to insert the node, do an ugly un-const cast and modify //the key (which is a smart pointer) to an equivalent one @@ -1138,7 +1138,7 @@ class segment_manager } //Allocates buffer for name + data, this can throw (it hurts) - void *buffer_ptr; + void *buffer_ptr; //Check if there is enough memory if(dothrow){ @@ -1149,7 +1149,7 @@ class segment_manager buffer_ptr = this->allocate (block_info.template total_size_with_header<intrusive_value_type>(), std::nothrow_t()); if(!buffer_ptr) - return 0; + return 0; } //Now construct the intrusive hook plus the header @@ -1184,7 +1184,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,10 +1197,10 @@ class segment_manager //!Generic named new function for //!named functions template<class CharT> - void * priv_generic_named_construct(unsigned char type, + void * priv_generic_named_construct(unsigned char type, const CharT *name, - size_type num, - bool try2find, + size_type num, + bool try2find, bool dothrow, ipcdetail::in_place_interface &table, IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, @@ -1227,12 +1227,12 @@ class segment_manager //------------------------------- //Insert the node. This can throw. //First, we want to know if the key is already present before - //we allocate any memory, and if the key is not present, we + //we allocate any memory, and if the key is not present, we //want to allocate all memory in a single buffer that will //contain the name and the user buffer. // //Since equal_range(key) + insert(hint, value) approach is - //quite inefficient in container implementations + //quite inefficient in container implementations //(they re-test if the position is correct), I've chosen //to insert the node, do an ugly un-const cast and modify //the key (which is a smart pointer) to an equivalent one @@ -1265,7 +1265,7 @@ class segment_manager value_eraser<index_type> v_eraser(index, it); //Allocates buffer for name + data, this can throw (it hurts) - void *buffer_ptr; + void *buffer_ptr; block_header_t * hdr; //Allocate and construct the headers @@ -1277,7 +1277,7 @@ class segment_manager else{ buffer_ptr = this->allocate(total_size, std::nothrow_t()); if(!buffer_ptr) - return 0; + return 0; } index_it *idr = new(buffer_ptr) index_it(it); hdr = block_header_t::template from_first_header<index_it>(idr); @@ -1289,7 +1289,7 @@ class segment_manager else{ buffer_ptr = this->allocate(block_info.total_size(), std::nothrow_t()); if(!buffer_ptr) - return 0; + return 0; } hdr = static_cast<block_header_t*>(buffer_ptr); } @@ -1303,7 +1303,7 @@ class segment_manager std::char_traits<CharT>::copy(name_ptr, name, namelen+1); //Do the ugly cast, please mama, forgive me! - //This new key points to an identical string, so it must have the + //This new key points to an identical string, so it must have the //same position than the overwritten key according to the predicate const_cast<key_type &>(it->first).name(name_ptr); it->second.m_ptr = hdr; @@ -1346,7 +1346,7 @@ 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) diff --git a/boost/interprocess/shared_memory_object.hpp b/boost/interprocess/shared_memory_object.hpp index 7c8fcf61bd..f3bc7ba173 100644 --- a/boost/interprocess/shared_memory_object.hpp +++ b/boost/interprocess/shared_memory_object.hpp @@ -28,7 +28,7 @@ #if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS_ONLY) # include <sys/shm.h> //System V shared memory... #elif defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS) -# include <fcntl.h> //O_CREAT, O_*... +# include <fcntl.h> //O_CREAT, O_*... # include <sys/mman.h> //shm_xxx # include <unistd.h> //ftruncate, close # include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU, @@ -71,26 +71,26 @@ class shared_memory_object shared_memory_object(open_or_create_t, const char *name, mode_t mode, const permissions &perm = permissions()) { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm); } - //!Tries to open a shared memory object with name "name", with the access mode "mode". + //!Tries to open a shared memory object with name "name", with the access mode "mode". //!If the file does not previously exist, it throws an error. shared_memory_object(open_only_t, const char *name, mode_t mode) { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); } - //!Moves the ownership of "moved"'s shared memory object to *this. - //!After the call, "moved" does not represent any shared memory object. + //!Moves the ownership of "moved"'s shared memory object to *this. + //!After the call, "moved" does not represent any shared memory object. //!Does not throw shared_memory_object(BOOST_RV_REF(shared_memory_object) moved) : m_handle(file_handle_t(ipcdetail::invalid_file())) { this->swap(moved); } //!Moves the ownership of "moved"'s shared memory to *this. - //!After the call, "moved" does not represent any shared memory. + //!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 +99,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); @@ -142,11 +142,11 @@ class shared_memory_object /// @cond -inline shared_memory_object::shared_memory_object() +inline shared_memory_object::shared_memory_object() : m_handle(file_handle_t(ipcdetail::invalid_file())) {} -inline shared_memory_object::~shared_memory_object() +inline shared_memory_object::~shared_memory_object() { this->priv_close(); } @@ -157,10 +157,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 @@ -268,7 +268,7 @@ inline bool use_filesystem_based_posix() } //shared_memory_object_detail inline bool shared_memory_object::priv_open_or_create - (ipcdetail::create_enum_t type, + (ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm) { diff --git a/boost/interprocess/smart_ptr/deleter.hpp b/boost/interprocess/smart_ptr/deleter.hpp index 4aba772975..3a07ccd8f4 100644 --- a/boost/interprocess/smart_ptr/deleter.hpp +++ b/boost/interprocess/smart_ptr/deleter.hpp @@ -26,9 +26,9 @@ //!Describes the functor to delete objects from the segment. namespace boost { -namespace interprocess { +namespace interprocess { -//!A deleter that uses the segment manager's destroy_ptr +//!A deleter that uses the segment manager's destroy_ptr //!function to destroy the passed pointer resource. //! //!This deleter is used @@ -56,7 +56,7 @@ class deleter { mp_mngr->destroy_ptr(ipcdetail::to_raw_pointer(p)); } }; -} //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 0150ef6c00..7daaee6ea4 100644 --- a/boost/interprocess/smart_ptr/detail/shared_count.hpp +++ b/boost/interprocess/smart_ptr/detail/shared_count.hpp @@ -28,7 +28,7 @@ #include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp> #include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp> #include <boost/interprocess/detail/utilities.hpp> -#include <boost/container/allocator/allocator_traits.hpp> +#include <boost/container/allocator_traits.hpp> #include <boost/detail/no_exceptions_support.hpp> #include <functional> // std::less @@ -99,7 +99,7 @@ class shared_count counted_impl_allocator alloc(a); m_pi = alloc.allocate(1); //Anti-exception deallocator - scoped_ptr<counted_impl, + scoped_ptr<counted_impl, scoped_ptr_dealloc_functor<counted_impl_allocator> > deallocator(m_pi, alloc); //It's more correct to use VoidAllocator::construct but @@ -116,7 +116,7 @@ class shared_count } ~shared_count() // nothrow - { + { if(m_pi) m_pi->release(); } diff --git a/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp b/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp index 4e2e664c86..6a46bb75e6 100644 --- a/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp +++ b/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp @@ -26,7 +26,7 @@ #include <boost/interprocess/smart_ptr/detail/sp_counted_base.hpp> #include <boost/interprocess/smart_ptr/scoped_ptr.hpp> #include <boost/interprocess/detail/utilities.hpp> -#include <boost/container/allocator/allocator_traits.hpp> +#include <boost/container/allocator_traits.hpp> #include <boost/intrusive/pointer_traits.hpp> namespace boost { @@ -63,10 +63,10 @@ struct scoped_ptr_dealloc_functor { if (ptr) priv_deallocate(ptr, alloc_version()); } }; - + template<class A, class D> -class sp_counted_impl_pd +class sp_counted_impl_pd : public sp_counted_base , boost::container::allocator_traits<A>::template portable_rebind_alloc< sp_counted_impl_pd<A, D> >::type diff --git a/boost/interprocess/smart_ptr/intrusive_ptr.hpp b/boost/interprocess/smart_ptr/intrusive_ptr.hpp index 3f086f5360..f6d5c8b77c 100644 --- a/boost/interprocess/smart_ptr/intrusive_ptr.hpp +++ b/boost/interprocess/smart_ptr/intrusive_ptr.hpp @@ -33,12 +33,12 @@ namespace interprocess { //!The intrusive_ptr class template stores a pointer to an object //!with an embedded reference count. intrusive_ptr is parameterized on -//!T (the type of the object pointed to) and VoidPointer(a void pointer type +//!T (the type of the object pointed to) and VoidPointer(a void pointer type //!that defines the type of pointer that intrusive_ptr will store). //!intrusive_ptr<T, void *> defines a class with a T* member whereas //!intrusive_ptr<T, offset_ptr<void> > defines a class with a offset_ptr<T> member. //!Relies on unqualified calls to: -//! +//! //! void intrusive_ptr_add_ref(T * p); //! void intrusive_ptr_release(T * p); //! @@ -69,7 +69,7 @@ class intrusive_ptr intrusive_ptr(): m_ptr(0) {} - //!Constructor. Copies pointer and if "p" is not zero and + //!Constructor. Copies pointer and if "p" is not zero and //!"add_ref" is true calls intrusive_ptr_add_ref(to_raw_pointer(p)). //!Does not throw intrusive_ptr(const pointer &p, bool add_ref = true): m_ptr(p) @@ -101,7 +101,7 @@ class intrusive_ptr if(m_ptr != 0) intrusive_ptr_release(ipcdetail::to_raw_pointer(m_ptr)); } - //!Assignment operator. Equivalent to intrusive_ptr(r).swap(*this). + //!Assignment operator. Equivalent to intrusive_ptr(r).swap(*this). //!Does not throw intrusive_ptr & operator=(intrusive_ptr const & rhs) { @@ -109,7 +109,7 @@ class intrusive_ptr return *this; } - //!Assignment from related. Equivalent to intrusive_ptr(r).swap(*this). + //!Assignment from related. Equivalent to intrusive_ptr(r).swap(*this). //!Does not throw template<class U> intrusive_ptr & operator= (intrusive_ptr<U, VP> const & rhs) @@ -118,14 +118,14 @@ class intrusive_ptr return *this; } - //!Assignment from pointer. Equivalent to intrusive_ptr(r).swap(*this). + //!Assignment from pointer. Equivalent to intrusive_ptr(r).swap(*this). //!Does not throw intrusive_ptr & operator=(pointer rhs) { this_type(rhs).swap(*this); return *this; } - + //!Returns a reference to the internal pointer. //!Does not throw pointer &get() @@ -175,7 +175,7 @@ class intrusive_ptr //!Returns a.get() == b.get(). //!Does not throw template<class T, class U, class VP> inline -bool operator==(intrusive_ptr<T, VP> const & a, +bool operator==(intrusive_ptr<T, VP> const & a, intrusive_ptr<U, VP> const & b) { return a.get() == b.get(); } @@ -217,11 +217,11 @@ bool operator!=(const typename intrusive_ptr<T, VP>::pointer &a, //!Returns a.get() < b.get(). //!Does not throw template<class T, class VP> inline -bool operator<(intrusive_ptr<T, VP> const & a, +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. @@ -233,7 +233,7 @@ void swap(intrusive_ptr<T, VP> & lhs, // operator<< template<class E, class T, class Y, class VP> -inline std::basic_ostream<E, T> & operator<< +inline std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y, VP> const & p) { os << p.get(); return os; } diff --git a/boost/interprocess/smart_ptr/scoped_ptr.hpp b/boost/interprocess/smart_ptr/scoped_ptr.hpp index 1885838ffe..a3755d3592 100644 --- a/boost/interprocess/smart_ptr/scoped_ptr.hpp +++ b/boost/interprocess/smart_ptr/scoped_ptr.hpp @@ -27,14 +27,14 @@ namespace boost { namespace interprocess { -//!scoped_ptr stores a pointer to a dynamically allocated object. +//!scoped_ptr stores a pointer to a dynamically allocated object. //!The object pointed to is guaranteed to be deleted, either on destruction //!of the scoped_ptr, or via an explicit reset. The user can avoid this //!deletion using release(). -//!scoped_ptr is parameterized on T (the type of the object pointed to) and +//!scoped_ptr is parameterized on T (the type of the object pointed to) and //!Deleter (the functor to be executed to delete the internal pointer). -//!The internal pointer will be of the same pointer type as typename -//!Deleter::pointer type (that is, if typename Deleter::pointer is +//!The internal pointer will be of the same pointer type as typename +//!Deleter::pointer type (that is, if typename Deleter::pointer is //!offset_ptr<void>, the internal pointer will be offset_ptr<T>). template<class T, class Deleter> class scoped_ptr @@ -60,10 +60,10 @@ class scoped_ptr : Deleter(d), m_ptr(p) // throws if pointer/Deleter copy ctor throws {} - //!If the stored pointer is not 0, destroys the object pointed to by the stored pointer. + //!If the stored pointer is not 0, destroys the object pointed to by the stored pointer. //!calling the operator() of the stored deleter. Never throws ~scoped_ptr() - { + { if(m_ptr){ Deleter &del = static_cast<Deleter&>(*this); del(m_ptr); diff --git a/boost/interprocess/smart_ptr/shared_ptr.hpp b/boost/interprocess/smart_ptr/shared_ptr.hpp index 61829078e8..5ede547a3f 100644 --- a/boost/interprocess/smart_ptr/shared_ptr.hpp +++ b/boost/interprocess/smart_ptr/shared_ptr.hpp @@ -52,7 +52,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){ @@ -66,17 +66,17 @@ inline void sp_enable_shared_from_this(shared_count<T, VoidAllocator, Deleter> c } // namespace ipcdetail -//!shared_ptr stores a pointer to a dynamically allocated object. -//!The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to +//!shared_ptr stores a pointer to a dynamically allocated object. +//!The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to //!it is destroyed or reset. //! -//!shared_ptr is parameterized on +//!shared_ptr is parameterized on //!T (the type of the object pointed to), VoidAllocator (the void allocator to be used -//!to allocate the auxiliary data) and Deleter (the deleter whose +//!to allocate the auxiliary data) and Deleter (the deleter whose //!operator() will be used to delete the object. //! -//!The internal pointer will be of the same pointer type as typename -//!VoidAllocator::pointer type (that is, if typename VoidAllocator::pointer is +//!The internal pointer will be of the same pointer type as typename +//!VoidAllocator::pointer type (that is, if typename VoidAllocator::pointer is //!offset_ptr<void>, the internal pointer will be offset_ptr<T>). //! //!Because the implementation uses reference counting, cycles of shared_ptr @@ -125,7 +125,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:: @@ -134,25 +134,30 @@ class shared_ptr BOOST_STATIC_ASSERT((ipcdetail::is_same<pointer, ParameterPointer>::value) || (ipcdetail::is_pointer<pointer>::value)); - ipcdetail::sp_enable_shared_from_this<T, VoidAllocator, Deleter>( m_pn, ipcdetail::to_raw_pointer(p), ipcdetail::to_raw_pointer(p) ); + ipcdetail::sp_enable_shared_from_this<T, VoidAllocator, Deleter>( m_pn, ipcdetail::to_raw_pointer(p), ipcdetail::to_raw_pointer(p) ); } + //!Copy constructs a shared_ptr. If r is empty, constructs an empty shared_ptr. Otherwise, constructs + //!a shared_ptr that shares ownership with r. Never throws. + shared_ptr(const shared_ptr &r) + : m_pn(r.m_pn) // never throws + {} - //!Constructs a shared_ptr that shares ownership with r and stores p. + //!Constructs a shared_ptr that shares ownership with other and stores p. //!Postconditions: get() == p && use_count() == r.use_count(). //!Throws: nothing. shared_ptr(const shared_ptr &other, const pointer &p) : m_pn(other.m_pn, p) {} - //!If r is empty, constructs an empty shared_ptr. Otherwise, constructs + //!If r is empty, constructs an empty shared_ptr. Otherwise, constructs //!a shared_ptr that shares ownership with r. Never throws. template<class Y> shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r) : m_pn(r.m_pn) // never throws {} - //!Constructs a shared_ptr that shares ownership with r and stores + //!Constructs a shared_ptr that shares ownership with r and stores //!a copy of the pointer stored in r. template<class Y> explicit shared_ptr(weak_ptr<Y, VoidAllocator, Deleter> const & r) @@ -170,19 +175,19 @@ class shared_ptr 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()))) - , r.m_pn) + , r.m_pn) {} template<class Y> shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::const_cast_tag) : m_pn( pointer(const_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer()))) - , r.m_pn) + , r.m_pn) {} template<class Y> shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::dynamic_cast_tag) : m_pn( pointer(dynamic_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer()))) - , r.m_pn) + , r.m_pn) { if(!m_pn.to_raw_pointer()){ // need to allocate new counter -- the cast failed m_pn = ipcdetail::shared_count<T, VoidAllocator, Deleter>(); @@ -218,15 +223,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:: @@ -234,7 +239,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> @@ -248,12 +253,12 @@ class shared_ptr reference operator* () const // never throws { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return *m_pn.to_raw_pointer(); } - //!Returns the pointer pointing + //!Returns the pointer pointing //!to the owned object pointer operator-> () const // never throws { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return m_pn.to_raw_pointer(); } - //!Returns the pointer pointing + //!Returns the pointer pointing //!to the owned object pointer get() const // never throws { return m_pn.to_raw_pointer(); } @@ -292,7 +297,7 @@ class shared_ptr /// @cond - template<class T2, class A2, class Deleter2> + template<class T2, class A2, class Deleter2> bool _internal_less(shared_ptr<T2, A2, Deleter2> const & rhs) const { return m_pn < rhs.m_pn; } @@ -311,19 +316,19 @@ class shared_ptr /// @endcond }; // shared_ptr -template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline +template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline bool operator==(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b) { return a.get() == b.get(); } -template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline +template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline bool operator!=(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b) { return a.get() != b.get(); } -template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline +template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline bool operator<(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b) { return a._internal_less(b); } -template<class T, class VoidAllocator, class Deleter> inline +template<class T, class VoidAllocator, class Deleter> inline void swap(shared_ptr<T, VoidAllocator, Deleter> & a, shared_ptr<T, VoidAllocator, Deleter> & b) { a.swap(b); } @@ -331,11 +336,11 @@ template<class T, class VoidAllocator, class Deleter, class U> inline shared_ptr<T, VoidAllocator, Deleter> static_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r) { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::static_cast_tag()); } -template<class T, class VoidAllocator, class Deleter, class U> inline +template<class T, class VoidAllocator, class Deleter, class U> inline shared_ptr<T, VoidAllocator, Deleter> const_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r) { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::const_cast_tag()); } -template<class T, class VoidAllocator, class Deleter, class U> inline +template<class T, class VoidAllocator, class Deleter, class U> inline shared_ptr<T, VoidAllocator, Deleter> dynamic_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r) { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::dynamic_cast_tag()); } @@ -346,7 +351,7 @@ T * to_raw_pointer(shared_ptr<T, VoidAllocator, Deleter> const & p) // operator<< template<class E, class T, class Y, class VoidAllocator, class Deleter> inline -std::basic_ostream<E, T> & operator<< +std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y, VoidAllocator, Deleter> const & p) { os << p.get(); return os; } diff --git a/boost/interprocess/smart_ptr/unique_ptr.hpp b/boost/interprocess/smart_ptr/unique_ptr.hpp index 547038b69b..89cdb1e6e2 100644 --- a/boost/interprocess/smart_ptr/unique_ptr.hpp +++ b/boost/interprocess/smart_ptr/unique_ptr.hpp @@ -272,20 +272,20 @@ class unique_ptr //!Returns: A reference to the stored deleter. //! //!Throws: nothing. - deleter_reference get_deleter() + deleter_reference get_deleter() { return ptr_.second(); } //!Returns: A const reference to the stored deleter. //! //!Throws: nothing. - deleter_const_reference get_deleter() const + 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 + operator int nat::*() const { return ptr_.first() ? &nat::for_bool_ : 0; } //!Postcondition: get() == 0. @@ -328,7 +328,7 @@ class unique_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 @@ -539,7 +539,7 @@ template<class T, class ManagedMemory> inline typename managed_unique_ptr<T, ManagedMemory>::type make_managed_unique_ptr(T *constructed_object, ManagedMemory &managed_memory) { - return typename managed_unique_ptr<T, ManagedMemory>::type + return typename managed_unique_ptr<T, ManagedMemory>::type (constructed_object, managed_memory.template get_deleter<T>()); } diff --git a/boost/interprocess/smart_ptr/weak_ptr.hpp b/boost/interprocess/smart_ptr/weak_ptr.hpp index 7126d055aa..5202ede91c 100644 --- a/boost/interprocess/smart_ptr/weak_ptr.hpp +++ b/boost/interprocess/smart_ptr/weak_ptr.hpp @@ -31,7 +31,7 @@ namespace boost{ namespace interprocess{ //!The weak_ptr class template stores a "weak reference" to an object -//!that's already managed by a shared_ptr. To access the object, a weak_ptr +//!that's already managed by a shared_ptr. To access the object, a weak_ptr //!can be converted to a shared_ptr using the shared_ptr constructor or the //!member function lock. When the last shared_ptr to the object goes away //!and the object is deleted, the attempt to obtain a shared_ptr from the @@ -99,11 +99,11 @@ 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(); - m_pn.set_pointer(ref.get()); + m_pn.set_pointer(ref.get()); } //!Effects: If r is empty, constructs an empty weak_ptr; otherwise, @@ -126,7 +126,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 +174,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. @@ -196,10 +196,10 @@ class weak_ptr { ipcdetail::do_swap(m_pn, other.m_pn); } /// @cond - template<class T2, class A2, class D2> + 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) { @@ -216,7 +216,7 @@ class weak_ptr /// @endcond }; // weak_ptr -template<class T, class A, class D, class U, class A2, class D2> inline +template<class T, class A, class D, class U, class A2, class D2> inline bool operator<(weak_ptr<T, A, D> const & a, weak_ptr<U, A2, D2> const & b) { return a._internal_less(b); } diff --git a/boost/interprocess/streams/bufferstream.hpp b/boost/interprocess/streams/bufferstream.hpp index 834b3d1e01..3ae9f5e2dc 100644 --- a/boost/interprocess/streams/bufferstream.hpp +++ b/boost/interprocess/streams/bufferstream.hpp @@ -42,7 +42,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> @@ -53,7 +53,7 @@ namespace boost { namespace interprocess { //!a basic_xbufferstream. The elements are transmitted from a to a fixed //!size buffer template <class CharT, class CharTraits> -class basic_bufferbuf +class basic_bufferbuf : public std::basic_streambuf<CharT, CharTraits> { public: @@ -74,7 +74,7 @@ class basic_bufferbuf //!Constructor. Assigns formatting buffer. //!Does not throw. - explicit basic_bufferbuf(CharT *buffer, std::size_t length, + explicit basic_bufferbuf(CharT *buffer, 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) @@ -83,7 +83,7 @@ class basic_bufferbuf virtual ~basic_bufferbuf(){} public: - //!Returns the pointer and size of the internal buffer. + //!Returns the pointer and size of the internal buffer. //!Does not throw. std::pair<CharT *, std::size_t> buffer() const { return std::pair<CharT *, std::size_t>(m_buffer, m_length); } @@ -172,13 +172,13 @@ class basic_bufferbuf } virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, - std::ios_base::openmode mode + std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { bool in = false; bool out = false; - - const std::ios_base::openmode inout = + + const std::ios_base::openmode inout = std::ios_base::in | std::ios_base::out; if((mode & inout) == inout) { @@ -205,7 +205,7 @@ class basic_bufferbuf newoff = static_cast<std::streamoff>(m_length); break; case std::ios_base::cur: - newoff = in ? static_cast<std::streamoff>(this->gptr() - this->eback()) + newoff = in ? static_cast<std::streamoff>(this->gptr() - this->eback()) : static_cast<std::streamoff>(this->pptr() - this->pbase()); break; default: @@ -237,7 +237,7 @@ class basic_bufferbuf return pos_type(off); } - virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode + virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); } @@ -277,7 +277,7 @@ class basic_ibufferstream //!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), + : basic_ios_t(), base_t(0), m_buf(const_cast<CharT*>(buffer), length, mode | std::ios_base::in) { basic_ios_t::init(&m_buf); } @@ -289,12 +289,12 @@ class basic_ibufferstream basic_bufferbuf<CharT, CharTraits>* rdbuf() const { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); } - //!Returns the pointer and size of the internal buffer. + //!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(); } - //!Sets the underlying buffer to a new value. Resets + //!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); } @@ -335,7 +335,7 @@ class basic_obufferstream //!Does not throw. basic_obufferstream(CharT *buffer, std::size_t length, std::ios_base::openmode mode = std::ios_base::out) - : basic_ios_t(), base_t(0), + : basic_ios_t(), base_t(0), m_buf(buffer, length, mode | std::ios_base::out) { basic_ios_t::init(&m_buf); } @@ -347,12 +347,12 @@ class basic_obufferstream basic_bufferbuf<CharT, CharTraits>* rdbuf() const { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); } - //!Returns the pointer and size of the internal buffer. + //!Returns the pointer and size of the internal buffer. //!Does not throw. std::pair<CharT *, std::size_t> buffer() const { return m_buf.buffer(); } - //!Sets the underlying buffer to a new value. Resets + //!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); } @@ -367,7 +367,7 @@ class basic_obufferstream //!A basic_iostream class that uses a fixed size character buffer //!as its formatting buffer. template <class CharT, class CharTraits> -class basic_bufferstream +class basic_bufferstream : public std::basic_iostream<CharT, CharTraits> { @@ -388,7 +388,7 @@ class basic_bufferstream public: //!Constructor. //!Does not throw. - basic_bufferstream(std::ios_base::openmode mode + 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); } @@ -409,12 +409,12 @@ class basic_bufferstream basic_bufferbuf<CharT, CharTraits>* rdbuf() const { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); } - //!Returns the pointer and size of the internal buffer. + //!Returns the pointer and size of the internal buffer. //!Does not throw. std::pair<CharT *, std::size_t> buffer() const { return m_buf.buffer(); } - //!Sets the underlying buffer to a new value. Resets + //!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); } diff --git a/boost/interprocess/streams/vectorstream.hpp b/boost/interprocess/streams/vectorstream.hpp index 83041f2b2e..3cee7200ab 100644 --- a/boost/interprocess/streams/vectorstream.hpp +++ b/boost/interprocess/streams/vectorstream.hpp @@ -30,7 +30,7 @@ //!This file defines basic_vectorbuf, basic_ivectorstream, //!basic_ovectorstream, and basic_vectorstreamclasses. These classes //!represent streamsbufs and streams whose sources or destinations are -//!STL-like vectors that can be swapped with external vectors to avoid +//!STL-like vectors that can be swapped with external vectors to avoid //!unnecessary allocations/copies. #ifndef BOOST_INTERPROCESS_VECTORSTREAM_HPP @@ -43,7 +43,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> @@ -51,9 +51,9 @@ namespace boost { namespace interprocess { //!A streambuf class that controls the transmission of elements to and from -//!a basic_ivectorstream, basic_ovectorstream or basic_vectorstream. +//!a basic_ivectorstream, basic_ovectorstream or basic_vectorstream. //!It holds a character vector specified by CharVector template parameter -//!as its formatting buffer. The vector must have contiguous storage, like +//!as its formatting buffer. The vector must have contiguous storage, like //!std::vector, boost::interprocess::vector or boost::interprocess::basic_string template <class CharVector, class CharTraits> class basic_vectorbuf @@ -96,11 +96,11 @@ class basic_vectorbuf public: - //!Swaps the underlying vector with the passed vector. + //!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 @@ -118,8 +118,8 @@ class basic_vectorbuf //!Returns a const reference to the internal vector. //!Does not throw. - const vector_type &vector() const - { + 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 @@ -137,13 +137,13 @@ class basic_vectorbuf const_cast<basic_vectorbuf*>(this)->base_t::pbump(old_pos); } } - return m_vect; + return m_vect; } //!Preallocates memory from the internal vector. //!Resets the stream to the first position. //!Throws if the internals vector's memory allocation throws. - void reserve(typename vector_type::size_type size) + void reserve(typename vector_type::size_type size) { if (this->m_mode & std::ios_base::out && size > m_vect.size()){ typename vector_type::difference_type write_pos = base_t::pptr() - base_t::pbase(); @@ -282,7 +282,7 @@ class basic_vectorbuf } virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, - std::ios_base::openmode mode + std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { //Get seek mode @@ -325,7 +325,7 @@ class basic_vectorbuf newoff = limit; break; case std::ios_base::cur: - newoff = in ? static_cast<std::streamoff>(this->gptr() - this->eback()) + newoff = in ? static_cast<std::streamoff>(this->gptr() - this->eback()) : static_cast<std::streamoff>(this->pptr() - this->pbase()); break; default: @@ -350,7 +350,7 @@ class basic_vectorbuf return pos_type(newoff); } - virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode + virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); } @@ -413,7 +413,7 @@ class basic_ivectorstream basic_vectorbuf<CharVector, CharTraits>* rdbuf() const { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf()); } - //!Swaps the underlying vector with the passed vector. + //!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) @@ -421,18 +421,18 @@ class basic_ivectorstream //!Returns a const reference to the internal vector. //!Does not throw. - const vector_type &vector() const + const vector_type &vector() const { return m_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) + void reserve(typename vector_type::size_type size) { m_buf().reserve(size); } //!Calls clear() method of the internal vector. //!Resets the stream to the first position. - void clear() + void clear() { m_buf().clear(); } }; @@ -488,7 +488,7 @@ class basic_ovectorstream basic_vectorbuf<CharVector, CharTraits>* rdbuf() const { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf()); } - //!Swaps the underlying vector with the passed vector. + //!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) @@ -496,13 +496,13 @@ class basic_ovectorstream //!Returns a const reference to the internal vector. //!Does not throw. - const vector_type &vector() const + const vector_type &vector() const { return m_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) + void reserve(typename vector_type::size_type size) { m_buf().reserve(size); } }; @@ -534,7 +534,7 @@ class basic_vectorstream public: //!Constructor. Throws if vector_type default //!constructor throws. - basic_vectorstream(std::ios_base::openmode mode + 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); } @@ -554,7 +554,7 @@ class basic_vectorstream basic_vectorbuf<CharVector, CharTraits>* rdbuf() const { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf); } - //!Swaps the underlying vector with the passed vector. + //!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) @@ -562,18 +562,18 @@ class basic_vectorstream //!Returns a const reference to the internal vector. //!Does not throw. - const vector_type &vector() const + const vector_type &vector() const { return m_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) + void reserve(typename vector_type::size_type size) { m_buf.reserve(size); } //!Calls clear() method of the internal vector. //!Resets the stream to the first position. - void clear() + void clear() { m_buf.clear(); } /// @cond diff --git a/boost/interprocess/sync/detail/condition_algorithm_8a.hpp b/boost/interprocess/sync/detail/condition_algorithm_8a.hpp new file mode 100644 index 0000000000..eaad671cdf --- /dev/null +++ b/boost/interprocess/sync/detail/condition_algorithm_8a.hpp @@ -0,0 +1,316 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP +#define BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/sync/scoped_lock.hpp> +#include <limits> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// +// Condition variable algorithm taken from pthreads-win32 discussion. +// +// The algorithm was developed by Alexander Terekhov in colaboration with +// Louis Thomas. +// +// Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL +// +// semBlockLock - bin.semaphore +// semBlockQueue - semaphore +// mtxExternal - mutex or CS +// mtxUnblockLock - mutex or CS +// nWaitersGone - int +// nWaitersBlocked - int +// nWaitersToUnblock - int +// +// wait( timeout ) { +// +// [auto: register int result ] // error checking omitted +// [auto: register int nSignalsWasLeft ] +// [auto: register int nWaitersWasGone ] +// +// sem_wait( semBlockLock ); +// nWaitersBlocked++; +// sem_post( semBlockLock ); +// +// unlock( mtxExternal ); +// bTimedOut = sem_wait( semBlockQueue,timeout ); +// +// lock( mtxUnblockLock ); +// if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) { +// if ( bTimedOut ) { // timeout (or canceled) +// if ( 0 != nWaitersBlocked ) { +// nWaitersBlocked--; +// } +// else { +// nWaitersGone++; // count spurious wakeups. +// } +// } +// if ( 0 == --nWaitersToUnblock ) { +// if ( 0 != nWaitersBlocked ) { +// sem_post( semBlockLock ); // open the gate. +// nSignalsWasLeft = 0; // do not open the gate +// // below again. +// } +// else if ( 0 != (nWaitersWasGone = nWaitersGone) ) { +// nWaitersGone = 0; +// } +// } +// } +// else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or +// // spurious semaphore :-) +// sem_wait( semBlockLock ); +// nWaitersBlocked -= nWaitersGone; // something is going on here +// // - test of timeouts? :-) +// sem_post( semBlockLock ); +// nWaitersGone = 0; +// } +// unlock( mtxUnblockLock ); +// +// if ( 1 == nSignalsWasLeft ) { +// if ( 0 != nWaitersWasGone ) { +// // sem_adjust( semBlockQueue,-nWaitersWasGone ); +// while ( nWaitersWasGone-- ) { +// sem_wait( semBlockQueue ); // better now than spurious later +// } +// } sem_post( semBlockLock ); // open the gate +// } +// +// lock( mtxExternal ); +// +// return ( bTimedOut ) ? ETIMEOUT : 0; +// } +// +// signal(bAll) { +// +// [auto: register int result ] +// [auto: register int nSignalsToIssue] +// +// lock( mtxUnblockLock ); +// +// if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! +// if ( 0 == nWaitersBlocked ) { // NO-OP +// return unlock( mtxUnblockLock ); +// } +// if (bAll) { +// nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked; +// nWaitersBlocked = 0; +// } +// else { +// nSignalsToIssue = 1; +// nWaitersToUnblock++; +// nWaitersBlocked--; +// } +// } +// else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! +// sem_wait( semBlockLock ); // close the gate +// if ( 0 != nWaitersGone ) { +// nWaitersBlocked -= nWaitersGone; +// nWaitersGone = 0; +// } +// if (bAll) { +// nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked; +// nWaitersBlocked = 0; +// } +// else { +// nSignalsToIssue = nWaitersToUnblock = 1; +// nWaitersBlocked--; +// } +// } +// else { // NO-OP +// return unlock( mtxUnblockLock ); +// } +// +// unlock( mtxUnblockLock ); +// sem_post( semBlockQueue,nSignalsToIssue ); +// return result; +// } +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + + +// Required interface for ConditionMembers +// class ConditionMembers +// { +// typedef implementation_defined semaphore_type; +// typedef implementation_defined mutex_type; +// typedef implementation_defined integer_type; +// +// integer_type &get_nwaiters_blocked() +// integer_type &get_nwaiters_gone() +// integer_type &get_nwaiters_to_unblock() +// semaphore_type &get_sem_block_queue() +// semaphore_type &get_sem_block_lock() +// mutex_type &get_mtx_unblock_lock() +// }; +// +template<class ConditionMembers> +class condition_algorithm_8a +{ + private: + condition_algorithm_8a(); + ~condition_algorithm_8a(); + condition_algorithm_8a(const condition_algorithm_8a &); + condition_algorithm_8a &operator=(const condition_algorithm_8a &); + + typedef typename ConditionMembers::semaphore_type semaphore_type; + typedef typename ConditionMembers::mutex_type mutex_type; + typedef typename ConditionMembers::integer_type integer_type; + + // 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); + static void signal(ConditionMembers &data, bool broadcast); +}; + +template<class ConditionMembers> +inline void condition_algorithm_8a<ConditionMembers>::signal(ConditionMembers &data, bool broadcast) +{ + integer_type nsignals_to_issue; + + { + scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock()); + + if ( 0 != data.get_nwaiters_to_unblock() ) { // the gate is closed!!! + if ( 0 == data.get_nwaiters_blocked() ) { // NO-OP + //locker's destructor triggers data.get_mtx_unblock_lock().unlock() + return; + } + if (broadcast) { + data.get_nwaiters_to_unblock() += nsignals_to_issue = data.get_nwaiters_blocked(); + data.get_nwaiters_blocked() = 0; + } + else { + nsignals_to_issue = 1; + data.get_nwaiters_to_unblock()++; + data.get_nwaiters_blocked()--; + } + } + else if ( data.get_nwaiters_blocked() > data.get_nwaiters_gone() ) { // HARMLESS RACE CONDITION! + data.get_sem_block_lock().wait(); // close the gate + if ( 0 != data.get_nwaiters_gone() ) { + data.get_nwaiters_blocked() -= data.get_nwaiters_gone(); + data.get_nwaiters_gone() = 0; + } + if (broadcast) { + nsignals_to_issue = data.get_nwaiters_to_unblock() = data.get_nwaiters_blocked(); + data.get_nwaiters_blocked() = 0; + } + else { + nsignals_to_issue = data.get_nwaiters_to_unblock() = 1; + data.get_nwaiters_blocked()--; + } + } + else { // NO-OP + //locker's destructor triggers data.get_mtx_unblock_lock().unlock() + return; + } + //locker's destructor triggers data.get_mtx_unblock_lock().unlock() + } + data.get_sem_block_queue().post(nsignals_to_issue); +} + +template<class ConditionMembers> +template<class InterprocessMutex> +inline bool condition_algorithm_8a<ConditionMembers>::wait + (ConditionMembers &data, bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mtxExternal) +{ + //Initialize to avoid warnings + integer_type nsignals_was_left = 0; + integer_type nwaiters_was_gone = 0; + + data.get_sem_block_lock().wait(); + ++data.get_nwaiters_blocked(); + data.get_sem_block_lock().post(); + + struct scoped_unlock + { + InterprocessMutex & mut; + scoped_unlock(InterprocessMutex & m) + : mut(m) + { m.unlock(); } + + ~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); + + { + scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock()); + if ( 0 != (nsignals_was_left = data.get_nwaiters_to_unblock()) ) { + if ( bTimedOut ) { // timeout (or canceled) + if ( 0 != data.get_nwaiters_blocked() ) { + data.get_nwaiters_blocked()--; + } + else { + data.get_nwaiters_gone()++; // count spurious wakeups. + } + } + if ( 0 == --data.get_nwaiters_to_unblock() ) { + if ( 0 != data.get_nwaiters_blocked() ) { + data.get_sem_block_lock().post(); // open the gate. + nsignals_was_left = 0; // do not open the gate below again. + } + else if ( 0 != (nwaiters_was_gone = data.get_nwaiters_gone()) ) { + data.get_nwaiters_gone() = 0; + } + } + } + else if ( (std::numeric_limits<integer_type>::max)()/2 + == ++data.get_nwaiters_gone() ) { // timeout/canceled or spurious semaphore :-) + data.get_sem_block_lock().wait(); + data.get_nwaiters_blocked() -= data.get_nwaiters_gone(); // something is going on here - test of timeouts? :-) + data.get_sem_block_lock().post(); + data.get_nwaiters_gone() = 0; + } + //locker's destructor triggers data.get_mtx_unblock_lock().unlock() + } + + if ( 1 == nsignals_was_left ) { + if ( 0 != nwaiters_was_gone ) { + // sem_adjust( data.get_sem_block_queue(),-nwaiters_was_gone ); + while ( nwaiters_was_gone-- ) { + data.get_sem_block_queue().wait(); // better now than spurious later + } + } + data.get_sem_block_lock().post(); // open the gate + } + + //mtxExternal.lock(); called from unlocker + + return ( bTimedOut ) ? false : true; +} + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP diff --git a/boost/interprocess/sync/file_lock.hpp b/boost/interprocess/sync/file_lock.hpp index a60b814a4f..e0f75465fb 100644 --- a/boost/interprocess/sync/file_lock.hpp +++ b/boost/interprocess/sync/file_lock.hpp @@ -53,21 +53,21 @@ class file_lock //!exist or there are no operating system resources. file_lock(const char *name); - //!Moves the ownership of "moved"'s file mapping object to *this. - //!After the call, "moved" does not represent any file mapping object. + //!Moves the ownership of "moved"'s file mapping object to *this. + //!After the call, "moved" does not represent any file mapping object. //!Does not throw file_lock(BOOST_RV_REF(file_lock) moved) : m_file_hnd(file_handle_t(ipcdetail::invalid_file())) { this->swap(moved); } //!Moves the ownership of "moved"'s file mapping to *this. - //!After the call, "moved" does not represent any file mapping. + //!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 +81,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, @@ -101,12 +101,12 @@ class file_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. + //!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. + //!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(); @@ -120,21 +120,21 @@ class file_lock //!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. + //! mutex this succeeds. //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, returns false. + //! 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. + //! 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. + //!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(); /// @cond @@ -171,7 +171,7 @@ class file_lock 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; diff --git a/boost/interprocess/sync/interprocess_condition.hpp b/boost/interprocess/sync/interprocess_condition.hpp index b0e74fc342..9d0bea640e 100644 --- a/boost/interprocess/sync/interprocess_condition.hpp +++ b/boost/interprocess/sync/interprocess_condition.hpp @@ -30,9 +30,9 @@ #include <boost/interprocess/sync/posix/condition.hpp> #define BOOST_INTERPROCESS_USE_POSIX //Experimental... -//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) -// #include <boost/interprocess/sync/windows/condition.hpp> -// #define BOOST_INTERPROCESS_USE_WINDOWS +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/condition.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #include <boost/interprocess/sync/spin/condition.hpp> #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION @@ -70,7 +70,7 @@ class interprocess_condition //!liberating system resources. ~interprocess_condition(){} - //!If there is a thread waiting on *this, change that + //!If there is a thread waiting on *this, change that //!thread's state to ready. Otherwise there is no effect. void notify_one() { m_condition.notify_one(); } @@ -80,8 +80,8 @@ class interprocess_condition void notify_all() { m_condition.notify_all(); } - //!Releases the lock on the interprocess_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to + //!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) @@ -103,9 +103,9 @@ class interprocess_condition this->do_wait(*lock.mutex()); } - //!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, + //!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> @@ -120,8 +120,8 @@ class interprocess_condition return this->do_timed_wait(abs_time, *lock.mutex()); } - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); + //!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) diff --git a/boost/interprocess/sync/interprocess_mutex.hpp b/boost/interprocess/sync/interprocess_mutex.hpp index 478cf78cc3..8110c8472b 100644 --- a/boost/interprocess/sync/interprocess_mutex.hpp +++ b/boost/interprocess/sync/interprocess_mutex.hpp @@ -31,9 +31,9 @@ #include <boost/interprocess/sync/posix/mutex.hpp> #define BOOST_INTERPROCESS_USE_POSIX //Experimental... -//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) -// #include <boost/interprocess/sync/windows/mutex.hpp> -// #define BOOST_INTERPROCESS_USE_WINDOWS +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/mutex.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #include <boost/interprocess/sync/spin/mutex.hpp> #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION @@ -61,7 +61,7 @@ namespace interprocess { class interprocess_condition; -//!Wraps a interprocess_mutex that can be placed in shared memory and can be +//!Wraps a interprocess_mutex that can be placed in shared memory and can be //!shared between processes. Allows timed lock tries class interprocess_mutex { @@ -98,9 +98,9 @@ class interprocess_mutex //!Effects: The calling thread will try to obtain exclusive ownership of the //! mutex if it can do so in until the specified time is reached. If the //! mutex supports recursive locking, the mutex must be unlocked the same - //! number of times it is locked. + //! number of times it is locked. //!Returns: If the thread acquires ownership of the mutex, returns true, if - //! the timeout expires returns false. + //! the timeout expires returns false. //!Throws: interprocess_exception on error. bool timed_lock(const boost::posix_time::ptime &abs_time); diff --git a/boost/interprocess/sync/interprocess_recursive_mutex.hpp b/boost/interprocess/sync/interprocess_recursive_mutex.hpp index 308819ff27..3079108645 100644 --- a/boost/interprocess/sync/interprocess_recursive_mutex.hpp +++ b/boost/interprocess/sync/interprocess_recursive_mutex.hpp @@ -43,9 +43,9 @@ #include <boost/interprocess/sync/posix/recursive_mutex.hpp> #define BOOST_INTERPROCESS_USE_POSIX //Experimental... -//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) -// #include <boost/interprocess/sync/windows/recursive_mutex.hpp> -// #define BOOST_INTERPROCESS_USE_WINDOWS +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/recursive_mutex.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #include <boost/interprocess/sync/spin/recursive_mutex.hpp> #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION @@ -72,8 +72,8 @@ class mutex_traits; namespace boost { namespace interprocess { -//!Wraps a interprocess_mutex that can be placed in shared memory and can be -//!shared between processes. Allows several locking calls by the same +//!Wraps a interprocess_mutex that can be placed in shared memory and can be +//!shared between processes. Allows several locking calls by the same //!process. Allows timed lock tries class interprocess_recursive_mutex { @@ -99,7 +99,7 @@ class interprocess_recursive_mutex //!Throws: interprocess_exception on error. void lock(); - //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex + //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex //!is already locked, returns true when success. The mutex must be unlocked //!the same number of times it is locked. //!Throws: interprocess_exception if a severe error is found diff --git a/boost/interprocess/sync/interprocess_semaphore.hpp b/boost/interprocess/sync/interprocess_semaphore.hpp index 4ffcdcf691..2a2f34fdcf 100644 --- a/boost/interprocess/sync/interprocess_semaphore.hpp +++ b/boost/interprocess/sync/interprocess_semaphore.hpp @@ -29,9 +29,9 @@ #include <boost/interprocess/sync/posix/semaphore.hpp> #define BOOST_INTERPROCESS_USE_POSIX //Experimental... -//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) -// #include <boost/interprocess/sync/windows/semaphore.hpp> -// #define BOOST_INTERPROCESS_USE_WINDOWS +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/semaphore.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #include <boost/interprocess/sync/spin/semaphore.hpp> #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION @@ -45,7 +45,7 @@ namespace boost { namespace interprocess { -//!Wraps a interprocess_semaphore that can be placed in shared memory and can be +//!Wraps a interprocess_semaphore that can be placed in shared memory and can be //!shared between processes. Allows timed lock tries class interprocess_semaphore { @@ -55,7 +55,7 @@ class interprocess_semaphore interprocess_semaphore &operator=(const interprocess_semaphore &); /// @endcond public: - //!Creates a interprocess_semaphore with the given initial count. + //!Creates a interprocess_semaphore with the given initial count. //!interprocess_exception if there is an error.*/ interprocess_semaphore(unsigned int initialCount); @@ -69,7 +69,7 @@ class interprocess_semaphore void post(); //!Decrements the interprocess_semaphore. If the interprocess_semaphore value is not greater than zero, - //!then the calling process/thread blocks until it can decrement the counter. + //!then the calling process/thread blocks until it can decrement the counter. //!If there is an error an interprocess_exception exception is thrown. void wait(); @@ -95,7 +95,7 @@ class interprocess_semaphore #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) #undef BOOST_INTERPROCESS_USE_WINDOWS ipcdetail::windows_semaphore m_sem; - #else + #else #undef BOOST_INTERPROCESS_USE_POSIX ipcdetail::posix_semaphore m_sem; #endif //#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) diff --git a/boost/interprocess/sync/interprocess_upgradable_mutex.hpp b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp index 048407f4b3..8d5a452626 100644 --- a/boost/interprocess/sync/interprocess_upgradable_mutex.hpp +++ b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp @@ -30,7 +30,7 @@ namespace boost { namespace interprocess { -//!Wraps a interprocess_upgradable_mutex that can be placed in shared memory and can be +//!Wraps a interprocess_upgradable_mutex that can be placed in shared memory and can be //!shared between processes. Allows timed lock tries class interprocess_upgradable_mutex { @@ -67,13 +67,13 @@ class interprocess_upgradable_mutex //!Effects: The calling thread tries to acquire exclusive ownership of the mutex //! waiting if necessary until no other thread has exclusive, sharable or - //! upgradable ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! upgradable ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. 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. + //!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(); @@ -87,21 +87,21 @@ class interprocess_upgradable_mutex //!Effects: The calling thread tries to acquire sharable ownership of the mutex //! without waiting. If no other thread has exclusive ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, returns false. + //! 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. + //! 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. + //!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(); @@ -115,7 +115,7 @@ class interprocess_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! without waiting. If no other thread has exclusive or upgradable ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire upgradable ownership immediately returns true. //! If it has to wait, returns false. //!Throws: interprocess_exception on error. @@ -124,74 +124,74 @@ class interprocess_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! waiting if necessary until no other thread has exclusive or upgradable //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The calling thread releases the upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The calling thread releases the upgradable ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable(); //Demotions - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! upgradable ownership. This operation is non-blocking. + //! upgradable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_upgradable(); - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_sharable(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock_sharable(); //Promotions - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires //! exclusive ownership. This operation will block until all threads with - //! sharable ownership release their sharable lock. + //! sharable ownership release their sharable lock. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to //! acquire exclusive ownership. This operation will fail if there are threads - //! with sharable ownership, but it will maintain upgradable ownership. + //! with sharable ownership, but it will maintain upgradable ownership. //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to acquire //! exclusive ownership, waiting if necessary until abs_time. This operation will //! fail if there are threads with sharable ownership or timeout reaches, but it - //! will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. */ bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have sharable ownership of the mutex. + //!Precondition: The thread must have sharable ownership of the mutex. //!Effects: The thread atomically releases sharable ownership and tries to acquire //! exclusive ownership. This operation will fail if there are threads with sharable //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock(); - //!Precondition: The thread must have sharable ownership of the mutex. + //!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. + //! 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(); @@ -249,7 +249,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; } @@ -260,7 +260,7 @@ class interprocess_upgradable_mutex template<int Dummy> struct base_constants_t { - static const unsigned max_readers + static const unsigned max_readers = ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2)); }; typedef base_constants_t<0> constants; @@ -309,10 +309,10 @@ inline bool interprocess_upgradable_mutex::try_lock() { scoped_lock_t lock(m_mut, try_to_lock); - //If we can't lock or any has there is any exclusive, upgradable + //If we can't lock or any has there is any exclusive, upgradable //or sharable mark return false; - if(!lock.owns() - || this->m_ctrl.exclusive_in + if(!lock.owns() + || this->m_ctrl.exclusive_in || this->m_ctrl.num_upr_shar){ return false; } @@ -387,9 +387,9 @@ inline bool interprocess_upgradable_mutex::try_lock_upgradable() //The upgradable lock must fail //if an exclusive or upgradable lock has been acquired //or there are too many sharable locks - if(!lock.owns() - || this->m_ctrl.exclusive_in - || this->m_ctrl.upgradable_in + if(!lock.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers){ return false; } @@ -414,11 +414,11 @@ inline bool interprocess_upgradable_mutex::timed_lock_upgradable //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 + 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 + return!(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers); } @@ -561,7 +561,7 @@ inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock() //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; @@ -584,7 +584,7 @@ inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock() } //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; } @@ -598,7 +598,7 @@ inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock //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; @@ -618,10 +618,10 @@ inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock() { scoped_lock_t lock(m_mut, try_to_lock); - //If we can't lock or any has there is any exclusive, upgradable + //If we can't lock or any has there is any exclusive, upgradable //or sharable mark return false; - if(!lock.owns() - || this->m_ctrl.exclusive_in + if(!lock.owns() + || this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar != 1){ return false; @@ -638,7 +638,7 @@ inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradab //The upgradable lock must fail //if an exclusive or upgradable lock has been acquired if(!lock.owns() - || this->m_ctrl.exclusive_in + || this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ return false; } diff --git a/boost/interprocess/sync/mutex_family.hpp b/boost/interprocess/sync/mutex_family.hpp index a9215e24fe..b153ffea3e 100644 --- a/boost/interprocess/sync/mutex_family.hpp +++ b/boost/interprocess/sync/mutex_family.hpp @@ -29,7 +29,7 @@ namespace boost { namespace interprocess { -//!Describes interprocess_mutex family to use with Interprocess framework +//!Describes interprocess_mutex family to use with Interprocess framework //!based on boost::interprocess synchronization objects. struct mutex_family { @@ -37,7 +37,7 @@ struct mutex_family typedef boost::interprocess::interprocess_recursive_mutex recursive_mutex_type; }; -//!Describes interprocess_mutex family to use with Interprocess frameworks +//!Describes interprocess_mutex family to use with Interprocess frameworks //!based on null operation synchronization objects. struct null_mutex_family { diff --git a/boost/interprocess/sync/named_condition.hpp b/boost/interprocess/sync/named_condition.hpp index c5529eda6c..ca0205ad73 100644 --- a/boost/interprocess/sync/named_condition.hpp +++ b/boost/interprocess/sync/named_condition.hpp @@ -22,7 +22,12 @@ #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/shm/named_condition.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 +#else + #include <boost/interprocess/sync/shm/named_condition.hpp> +#endif //!\file //!Describes a named condition class for inter-process synchronization @@ -50,7 +55,7 @@ class named_condition //!If the condition can't be created throws interprocess_exception named_condition(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global condition with a name. + //!Opens or creates a global condition with a name. //!If the condition is created, this call is equivalent to //!named_condition(create_only_t, ... ) //!If the condition is already created, this call is equivalent @@ -71,7 +76,7 @@ class named_condition //!use remove(). ~named_condition(); - //!If there is a thread waiting on *this, change that + //!If there is a thread waiting on *this, change that //!thread's state to ready. Otherwise there is no effect.*/ void notify_one(); @@ -79,8 +84,8 @@ class named_condition //!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 + //!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); @@ -90,16 +95,16 @@ class named_condition 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, + //!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(); + //!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); @@ -110,7 +115,12 @@ class named_condition /// @cond private: - ipcdetail::shm_named_condition m_cond; + #if defined(BOOST_INTERPROCESS_USE_WINDOWS) + typedef ipcdetail::windows_named_condition condition_type; + #else + typedef ipcdetail::shm_named_condition condition_type; + #endif + condition_type m_cond; friend class ipcdetail::interprocess_tester; void dont_close_on_destruction() @@ -160,7 +170,7 @@ inline bool named_condition::timed_wait { return m_cond.timed_wait(lock, abs_time, pred); } inline bool named_condition::remove(const char *name) -{ return ipcdetail::shm_named_condition::remove(name); } +{ return condition_type::remove(name); } /// @endcond diff --git a/boost/interprocess/sync/named_mutex.hpp b/boost/interprocess/sync/named_mutex.hpp index 3e56b81794..c34193c697 100644 --- a/boost/interprocess/sync/named_mutex.hpp +++ b/boost/interprocess/sync/named_mutex.hpp @@ -24,7 +24,11 @@ #include <boost/interprocess/permissions.hpp> #if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) -#include <boost/interprocess/sync/posix/named_mutex.hpp> + #include <boost/interprocess/sync/posix/named_mutex.hpp> + #define BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/named_mutex.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #else #include <boost/interprocess/sync/shm/named_mutex.hpp> #endif @@ -37,7 +41,7 @@ namespace interprocess { class named_condition; -//!A mutex with a global name, so it can be found from different +//!A mutex with a global name, so it can be found from different //!processes. This mutex can't be placed in shared memory, and //!each process should have it's own named_mutex. class named_mutex @@ -56,7 +60,7 @@ class named_mutex //!Throws interprocess_exception on error. named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global mutex with a name. + //!Opens or creates a global mutex with a name. //!If the mutex is created, this call is equivalent to //!named_mutex(create_only_t, ... ) //!If the mutex is already created, this call is equivalent @@ -85,7 +89,7 @@ class named_mutex //!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 interprocess_mutex, returns false when interprocess_mutex //!is already locked, returns true when success. //!Throws interprocess_exception if a severe error is found bool try_lock(); @@ -104,15 +108,20 @@ class named_mutex friend class ipcdetail::interprocess_tester; void dont_close_on_destruction(); - #if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - typedef ipcdetail::posix_named_mutex impl_t; - impl_t m_mut; + #if defined(BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES) + typedef ipcdetail::posix_named_mutex impl_t; + impl_t m_mut; + #undef BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES + #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) + typedef ipcdetail::windows_named_mutex impl_t; + impl_t m_mut; + #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 impl_t; + impl_t m_mut; + public: + interprocess_mutex *mutex() const + { return m_mut.mutex(); } #endif /// @endcond diff --git a/boost/interprocess/sync/named_recursive_mutex.hpp b/boost/interprocess/sync/named_recursive_mutex.hpp index 28768cea6f..2d4b9b2416 100644 --- a/boost/interprocess/sync/named_recursive_mutex.hpp +++ b/boost/interprocess/sync/named_recursive_mutex.hpp @@ -20,7 +20,12 @@ #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> #include <boost/interprocess/permissions.hpp> -#include <boost/interprocess/sync/shm/named_recursive_mutex.hpp> +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/named_recursive_mutex.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS +#else + #include <boost/interprocess/sync/shm/named_recursive_mutex.hpp> +#endif //!\file //!Describes a named named_recursive_mutex class for inter-process synchronization @@ -32,7 +37,7 @@ namespace interprocess { namespace ipcdetail{ class interprocess_tester; } /// @endcond -//!A recursive mutex with a global name, so it can be found from different +//!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 @@ -49,7 +54,7 @@ class named_recursive_mutex //!If the recursive_mutex can't be created throws interprocess_exception named_recursive_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global recursive_mutex with a name. + //!Opens or creates a global recursive_mutex with a name. //!If the recursive_mutex is created, this call is equivalent to //!named_recursive_mutex(create_only_t, ... ) //!If the recursive_mutex is already created, this call is equivalent @@ -78,7 +83,7 @@ class named_recursive_mutex //!Throws interprocess_exception if a severe error is found. void lock(); - //!Tries to lock the named_recursive_mutex, returns false when named_recursive_mutex + //!Tries to lock the named_recursive_mutex, returns false when named_recursive_mutex //!is already locked, returns true when success. //!Throws interprocess_exception if a severe error is found. bool try_lock(); @@ -97,7 +102,12 @@ class named_recursive_mutex friend class ipcdetail::interprocess_tester; void dont_close_on_destruction(); - typedef ipcdetail::shm_named_recursive_mutex impl_t; + #if defined(BOOST_INTERPROCESS_USE_WINDOWS) + typedef ipcdetail::windows_named_recursive_mutex impl_t; + #undef BOOST_INTERPROCESS_USE_WINDOWS + #else + typedef ipcdetail::shm_named_recursive_mutex impl_t; + #endif impl_t m_mut; /// @endcond diff --git a/boost/interprocess/sync/named_semaphore.hpp b/boost/interprocess/sync/named_semaphore.hpp index 33e06964f9..39c9096fb6 100644 --- a/boost/interprocess/sync/named_semaphore.hpp +++ b/boost/interprocess/sync/named_semaphore.hpp @@ -25,6 +25,10 @@ #if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES) #include <boost/interprocess/sync/posix/named_semaphore.hpp> +//Experimental... +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/named_semaphore.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #else #include <boost/interprocess/sync/shm/named_semaphore.hpp> #endif @@ -35,8 +39,8 @@ namespace boost { namespace interprocess { -//!A semaphore with a global name, so it can be found from different -//!processes. Allows several resource sharing patterns and efficient +//!A semaphore with a global name, so it can be found from different +//!processes. Allows several resource sharing patterns and efficient //!acknowledgment mechanisms. class named_semaphore { @@ -49,11 +53,11 @@ class named_semaphore /// @endcond public: - //!Creates a global semaphore with a name, and an initial count. + //!Creates a global semaphore with a name, and an initial count. //!If the semaphore can't be created throws interprocess_exception named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); - //!Opens or creates a global semaphore with a name, and an initial count. + //!Opens or creates a global semaphore with a name, and an initial count. //!If the semaphore is created, this call is equivalent to //!named_semaphore(create_only_t, ...) //!If the semaphore is already created, this call is equivalent to @@ -80,7 +84,7 @@ class named_semaphore void post(); //!Decrements the semaphore. If the semaphore value is not greater than zero, - //!then the calling process/thread blocks until it can decrement the counter. + //!then the calling process/thread blocks until it can decrement the counter. //!If there is an error an interprocess_exception exception is thrown. void wait(); @@ -106,9 +110,12 @@ class named_semaphore void dont_close_on_destruction(); #if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES) - typedef ipcdetail::posix_named_semaphore impl_t; + typedef ipcdetail::posix_named_semaphore impl_t; + #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) + #undef BOOST_INTERPROCESS_USE_WINDOWS + typedef ipcdetail::windows_named_semaphore impl_t; #else - typedef ipcdetail::shm_named_semaphore impl_t; + typedef ipcdetail::shm_named_semaphore impl_t; #endif impl_t m_sem; /// @endcond diff --git a/boost/interprocess/sync/named_upgradable_mutex.hpp b/boost/interprocess/sync/named_upgradable_mutex.hpp index 61c6bb4086..c45fd08270 100644 --- a/boost/interprocess/sync/named_upgradable_mutex.hpp +++ b/boost/interprocess/sync/named_upgradable_mutex.hpp @@ -38,7 +38,7 @@ namespace ipcdetail{ class interprocess_tester; } class named_condition; -//!A upgradable mutex with a global name, so it can be found from different +//!A upgradable mutex with a global name, so it can be found from different //!processes. This mutex can't be placed in shared memory, and //!each process should have it's own named upgradable mutex. class named_upgradable_mutex @@ -52,11 +52,11 @@ class named_upgradable_mutex /// @endcond public: - //!Creates a global upgradable mutex with a name. + //!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, and an initial count. //!If the upgradable mutex is created, this call is equivalent to //!named_upgradable_mutex(create_only_t, ...) //!If the upgradable mutex is already created, this call is equivalent to @@ -95,13 +95,13 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire exclusive ownership of the mutex //! waiting if necessary until no other thread has exclusive, sharable or - //! upgradable ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! upgradable ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. 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. + //!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(); @@ -115,21 +115,21 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire sharable ownership of the mutex //! without waiting. If no other thread has exclusive ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, returns false. + //! 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. + //! 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. + //!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(); @@ -143,7 +143,7 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! without waiting. If no other thread has exclusive or upgradable ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire upgradable ownership immediately returns true. //! If it has to wait, returns false. //!Throws: interprocess_exception on error. @@ -152,66 +152,66 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! waiting if necessary until no other thread has exclusive or upgradable //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The calling thread releases the upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The calling thread releases the upgradable ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable(); //Demotions - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! upgradable ownership. This operation is non-blocking. + //! upgradable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_upgradable(); - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_sharable(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock_sharable(); //Promotions - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires //! exclusive ownership. This operation will block until all threads with - //! sharable ownership release it. + //! sharable ownership release it. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to //! acquire exclusive ownership. This operation will fail if there are threads - //! with sharable ownership, but it will maintain upgradable ownership. + //! with sharable ownership, but it will maintain upgradable ownership. //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to acquire //! exclusive ownership, waiting if necessary until abs_time. This operation will //! fail if there are threads with sharable ownership or timeout reaches, but it - //! will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have sharable ownership of the mutex. + //!Precondition: The thread must have sharable ownership of the mutex. //!Effects: The thread atomically releases sharable ownership and tries to acquire //! exclusive ownership. This operation will fail if there are threads with sharable //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock(); diff --git a/boost/interprocess/sync/posix/condition.hpp b/boost/interprocess/sync/posix/condition.hpp index 213e4ce8b5..48be099f60 100644 --- a/boost/interprocess/sync/posix/condition.hpp +++ b/boost/interprocess/sync/posix/condition.hpp @@ -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> @@ -44,7 +44,7 @@ class posix_condition //!liberating system resources. ~posix_condition(); - //!If there is a thread waiting on *this, change that + //!If there is a thread waiting on *this, change that //!thread's state to ready. Otherwise there is no effect. void notify_one(); @@ -52,8 +52,8 @@ class posix_condition //!If there are no waiting threads, notify_all() has no effect. void notify_all(); - //!Releases the lock on the posix_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to + //!Releases the lock on the posix_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to //!this->notify_one() or this->notify_all(), and then reacquires the lock. template <typename L> void wait(L& lock) @@ -75,9 +75,9 @@ class posix_condition this->do_wait(*lock.mutex()); } - //!Releases the lock on the posix_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!Releases the lock on the posix_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, //!and then reacquires the lock. //!Returns: false if time abs_time is reached, otherwise true. template <typename L> @@ -92,8 +92,8 @@ class posix_condition return this->do_timed_wait(abs_time, *lock.mutex()); } - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); + //!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) diff --git a/boost/interprocess/sync/posix/mutex.hpp b/boost/interprocess/sync/posix/mutex.hpp index 22e2ec04b9..393807c97a 100644 --- a/boost/interprocess/sync/posix/mutex.hpp +++ b/boost/interprocess/sync/posix/mutex.hpp @@ -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> @@ -80,7 +80,7 @@ inline posix_mutex::posix_mutex() mut.release(); } -inline posix_mutex::~posix_mutex() +inline posix_mutex::~posix_mutex() { int res = pthread_mutex_destroy(&m_mut); BOOST_ASSERT(res == 0);(void)res; @@ -88,7 +88,7 @@ inline posix_mutex::~posix_mutex() inline void posix_mutex::lock() { - if (pthread_mutex_lock(&m_mut) != 0) + if (pthread_mutex_lock(&m_mut) != 0) throw lock_exception(); } diff --git a/boost/interprocess/sync/posix/pthread_helpers.hpp b/boost/interprocess/sync/posix/pthread_helpers.hpp index c09ce200cf..bcbc44be33 100644 --- a/boost/interprocess/sync/posix/pthread_helpers.hpp +++ b/boost/interprocess/sync/posix/pthread_helpers.hpp @@ -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 { @@ -29,7 +29,7 @@ namespace ipcdetail{ #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED //!Makes pthread_mutexattr_t cleanup easy when using exceptions - struct mutexattr_wrapper + struct mutexattr_wrapper { //!Constructor mutexattr_wrapper(bool recursive = false) @@ -51,7 +51,7 @@ namespace ipcdetail{ }; //!Makes pthread_condattr_t cleanup easy when using exceptions - struct condattr_wrapper + struct condattr_wrapper { //!Constructor condattr_wrapper() @@ -86,7 +86,7 @@ namespace ipcdetail{ void release() {mp_mut = 0; } - private: + private: pthread_mutex_t *mp_mut; }; @@ -94,7 +94,7 @@ namespace ipcdetail{ class condition_initializer { public: - condition_initializer(pthread_cond_t &cond, pthread_condattr_t &cond_attr) + condition_initializer(pthread_cond_t &cond, pthread_condattr_t &cond_attr) : mp_cond(&cond) { if(pthread_cond_init(mp_cond, &cond_attr)!= 0) @@ -105,7 +105,7 @@ namespace ipcdetail{ void release() { mp_cond = 0; } - private: + private: pthread_cond_t *mp_cond; }; @@ -114,7 +114,7 @@ namespace ipcdetail{ #if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) //!Makes pthread_barrierattr_t cleanup easy when using exceptions - struct barrierattr_wrapper + struct barrierattr_wrapper { //!Constructor barrierattr_wrapper() @@ -138,8 +138,8 @@ namespace ipcdetail{ { public: //!Constructor. Takes barrier attributes to initialize the barrier - barrier_initializer(pthread_barrier_t &mut, - pthread_barrierattr_t &mut_attr, + barrier_initializer(pthread_barrier_t &mut, + pthread_barrierattr_t &mut_attr, int count) : mp_barrier(&mut) { @@ -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/recursive_mutex.hpp b/boost/interprocess/sync/posix/recursive_mutex.hpp index baa670fa9a..456c9a4874 100644 --- a/boost/interprocess/sync/posix/recursive_mutex.hpp +++ b/boost/interprocess/sync/posix/recursive_mutex.hpp @@ -31,7 +31,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> @@ -78,7 +78,7 @@ inline posix_recursive_mutex::~posix_recursive_mutex() inline void posix_recursive_mutex::lock() { - if (pthread_mutex_lock(&m_mut) != 0) + if (pthread_mutex_lock(&m_mut) != 0) throw lock_exception(); } diff --git a/boost/interprocess/sync/posix/semaphore_wrapper.hpp b/boost/interprocess/sync/posix/semaphore_wrapper.hpp index 1aeef47662..22184cda9d 100644 --- a/boost/interprocess/sync/posix/semaphore_wrapper.hpp +++ b/boost/interprocess/sync/posix/semaphore_wrapper.hpp @@ -18,7 +18,7 @@ #include <boost/interprocess/detail/tmp_dir_helpers.hpp> #include <boost/interprocess/permissions.hpp> -#include <fcntl.h> //O_CREAT, O_*... +#include <fcntl.h> //O_CREAT, O_*... #include <unistd.h> //close #include <string> //std::string #include <semaphore.h> //sem_* family, SEM_VALUE_MAX @@ -42,7 +42,7 @@ namespace interprocess { namespace ipcdetail { inline bool semaphore_open - (sem_t *&handle, create_enum_t type, const char *origname, + (sem_t *&handle, create_enum_t type, const char *origname, unsigned int count = 0, const permissions &perm = permissions()) { std::string name; @@ -103,7 +103,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); } } @@ -138,7 +138,7 @@ inline void semaphore_init(sem_t *handle, unsigned int initialCount) inline void semaphore_destroy(sem_t *handle) { int ret = sem_destroy(handle); - if(ret != 0){ + if(ret != 0){ BOOST_ASSERT(0); } } diff --git a/boost/interprocess/sync/scoped_lock.hpp b/boost/interprocess/sync/scoped_lock.hpp index bfef63a30a..61fe93e5b3 100644 --- a/boost/interprocess/sync/scoped_lock.hpp +++ b/boost/interprocess/sync/scoped_lock.hpp @@ -89,7 +89,7 @@ class scoped_lock : mp_mutex(&m), m_locked(true) {} - //!Effects: m.try_lock(). + //!Effects: m.try_lock(). //!Postconditions: mutex() == &m. owns() == the return value of the //! m.try_lock() executed within the constructor. //!Notes: The constructor will take ownership of the mutex if it can do @@ -101,7 +101,7 @@ class scoped_lock : mp_mutex(&m), m_locked(mp_mutex->try_lock()) {} - //!Effects: m.timed_lock(abs_time). + //!Effects: m.timed_lock(abs_time). //!Postconditions: mutex() == &m. owns() == the return value of the //! m.timed_lock(abs_time) executed within the constructor. //!Notes: The constructor will take ownership of the mutex if it can do @@ -128,7 +128,7 @@ class scoped_lock { mp_mutex = scop.release(); } //!Effects: If upgr.owns() then calls unlock_upgradable_and_lock() on the - //! referenced mutex. upgr.release() is called. + //! referenced mutex. upgr.release() is called. //!Postconditions: mutex() == the value upgr.mutex() had before the construction. //! upgr.mutex() == 0. owns() == upgr.owns() before the construction. //! upgr.owns() == false after the construction. @@ -155,12 +155,12 @@ class scoped_lock //!Effects: If upgr.owns() then calls try_unlock_upgradable_and_lock() on the //!referenced mutex: //! a)if try_unlock_upgradable_and_lock() returns true then mutex() obtains - //! the value from upgr.release() and owns() is set to true. + //! 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 - //! a default construction. + //! 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 + //! and owns() is set to false //!Notes: This construction will not block. It will try to obtain mutex //! ownership from upgr immediately, while changing the lock type from a //! "read lock" to a "write lock". If the "read lock" isn't held in the @@ -186,12 +186,12 @@ class scoped_lock //!Effects: If upgr.owns() then calls timed_unlock_upgradable_and_lock(abs_time) //! on the referenced mutex: //! a)if timed_unlock_upgradable_and_lock(abs_time) returns true then mutex() - //! obtains the value from upgr.release() and owns() is set to true. + //! obtains the value from upgr.release() and owns() is set to true. //! b)if timed_unlock_upgradable_and_lock(abs_time) returns false then upgr //! is 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 + //! and owns() is set to false //!Notes: This construction will not block. It will try to obtain mutex ownership //! from upgr immediately, while changing the lock type from a "read lock" to a //! "write lock". If the "read lock" isn't held in the first place, the mutex @@ -214,14 +214,14 @@ class scoped_lock } //!Effects: If shar.owns() then calls try_unlock_sharable_and_lock() on the - //!referenced mutex. + //!referenced mutex. //! a)if try_unlock_sharable_and_lock() returns true then mutex() obtains - //! the value from shar.release() and owns() is set to true. + //! the value from shar.release() and owns() is set to true. //! b)if try_unlock_sharable_and_lock() returns false then shar is //! unaffected and this scoped_lock construction has the same - //! effects as a default construction. + //! effects as a default construction. //! c)Else shar.owns() is false. mutex() obtains the value from - //! shar.release() and owns() is set to false + //! shar.release() and owns() is set to false //!Notes: This construction will not block. It will try to obtain mutex //! ownership from shar immediately, while changing the lock type from a //! "read lock" to a "write lock". If the "read lock" isn't held in the @@ -253,13 +253,13 @@ class scoped_lock } //!Effects: If owns() before the call, then unlock() is called on mutex(). - //! *this gets the state of scop and scop gets set to a default constructed state. + //! *this gets the state of scop and scop gets set to a default constructed state. //!Notes: With a recursive mutex it is possible that both this and scop own //! the same mutex before the assignment. In this case, this will own the //! 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(); @@ -281,7 +281,7 @@ class scoped_lock } //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() - //! exception. Calls try_lock() on the referenced mutex. + //! exception. Calls try_lock() on the referenced mutex. //!Postconditions: owns() == the value returned from mutex()->try_lock(). //!Notes: The scoped_lock changes from a state of not owning the mutex, to //! owning the mutex, but only if blocking was not required. If the @@ -348,8 +348,8 @@ class scoped_lock m_locked = false; return mut; } - - //!Effects: Swaps state with moved lock. + + //!Effects: Swaps state with moved lock. //!Throws: Nothing. void swap( scoped_lock<mutex_type> &other) { @@ -359,7 +359,7 @@ class scoped_lock /// @cond private: - mutex_type *mp_mutex; + mutex_type *mp_mutex; bool m_locked; /// @endcond }; diff --git a/boost/interprocess/sync/sharable_lock.hpp b/boost/interprocess/sync/sharable_lock.hpp index c8b7c1d26e..9342e45a46 100644 --- a/boost/interprocess/sync/sharable_lock.hpp +++ b/boost/interprocess/sync/sharable_lock.hpp @@ -67,7 +67,7 @@ class sharable_lock {} //!Effects: m.lock_sharable(). - //!Postconditions: owns() == true and mutex() == &m. + //!Postconditions: owns() == true and mutex() == &m. //!Notes: The constructor will take sharable-ownership of the mutex. If //! another thread already owns the mutex with exclusive ownership //! (scoped_lock), this thread will block until the mutex is released. @@ -104,7 +104,7 @@ class sharable_lock : mp_mutex(&m), m_locked(false) { m_locked = mp_mutex->try_lock_sharable(); } - //!Effects: m.timed_lock_sharable(abs_time) + //!Effects: m.timed_lock_sharable(abs_time) //!Postconditions: mutex() == &m. owns() == the return value of the //! m.timed_lock_sharable() executed within the constructor. //!Notes: The constructor will take sharable-ownership of the mutex if it @@ -132,7 +132,7 @@ class sharable_lock //! referenced mutex. //!Postconditions: mutex() == the value upgr.mutex() had before the construction. //! upgr.mutex() == 0 owns() == the value of upgr.owns() before construction. - //! upgr.owns() == false after the construction. + //! upgr.owns() == false after the construction. //!Notes: If upgr is locked, this constructor will lock this sharable_lock while //! unlocking upgr. Only a moved sharable_lock's will match this //! signature. An non-moved upgradable_lock can be moved with the expression: @@ -156,7 +156,7 @@ class sharable_lock //! scop.mutex() == 0 owns() == scop.owns() before the constructor. After the //! construction, scop.owns() == false. //!Notes: If scop is locked, this constructor will transfer the exclusive ownership - //! to a sharable-ownership of this sharable_lock. + //! to a sharable-ownership of this sharable_lock. //! Only a moved scoped_lock's will match this //! signature. An non-moved scoped_lock can be moved with the expression: //! "boost::move(lock);". @@ -184,12 +184,12 @@ class sharable_lock } //!Effects: If owns() before the call, then unlock_sharable() is called on mutex(). - //! *this gets the state of upgr and upgr gets set to a default constructed state. + //! *this gets the state of upgr and upgr gets set to a default constructed state. //!Notes: With a recursive mutex it is possible that both this and upgr own the mutex //! before the assignment. In this case, this will own the mutex after the assignment //! (and upgr will not), but the mutex's lock count will be decremented by one. sharable_lock &operator=(BOOST_RV_REF(sharable_lock<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); @@ -282,7 +282,7 @@ class sharable_lock return mut; } - //!Effects: Swaps state with moved lock. + //!Effects: Swaps state with moved lock. //!Throws: Nothing. void swap(sharable_lock<mutex_type> &other) { diff --git a/boost/interprocess/sync/shm/named_condition.hpp b/boost/interprocess/sync/shm/named_condition.hpp index 0d67c25757..9d7cd77e11 100644 --- a/boost/interprocess/sync/shm/named_condition.hpp +++ b/boost/interprocess/sync/shm/named_condition.hpp @@ -28,7 +28,7 @@ #include <boost/interprocess/sync/shm/named_creation_functor.hpp> #include <boost/interprocess/sync/named_mutex.hpp> #include <boost/interprocess/permissions.hpp> -#if defined BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES +#if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) #include <boost/interprocess/sync/interprocess_mutex.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #endif @@ -42,7 +42,7 @@ namespace interprocess { namespace ipcdetail { /// @cond -namespace ipcdetail{ class interprocess_tester; } +class interprocess_tester; /// @endcond //! A global condition variable that can be created by name. @@ -61,7 +61,7 @@ class shm_named_condition //!If the condition can't be created throws interprocess_exception shm_named_condition(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global condition with a name. + //!Opens or creates a global condition with a name. //!If the condition is created, this call is equivalent to //!shm_named_condition(create_only_t, ... ) //!If the condition is already created, this call is equivalent @@ -82,7 +82,7 @@ class shm_named_condition //!use remove(). ~shm_named_condition(); - //!If there is a thread waiting on *this, change that + //!If there is a thread waiting on *this, change that //!thread's state to ready. Otherwise there is no effect.*/ void notify_one(); @@ -90,8 +90,8 @@ class shm_named_condition //!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 + //!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); @@ -101,16 +101,16 @@ class shm_named_condition 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, + //!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(); + //!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); @@ -147,6 +147,9 @@ class shm_named_condition void unlock() { l_.lock(); } }; + //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_; } @@ -156,7 +159,7 @@ class shm_named_condition { //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); @@ -173,18 +176,18 @@ class shm_named_condition { //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); + //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); + 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); + //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 + #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) template<class Lock> class lock_wrapper { @@ -210,7 +213,7 @@ class shm_named_condition private: Lock &l_; }; - #endif + #endif //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) friend class boost::interprocess::ipcdetail::interprocess_tester; void dont_close_on_destruction(); diff --git a/boost/interprocess/sync/shm/named_creation_functor.hpp b/boost/interprocess/sync/shm/named_creation_functor.hpp index 11a1db1d6f..9d752c837a 100644 --- a/boost/interprocess/sync/shm/named_creation_functor.hpp +++ b/boost/interprocess/sync/shm/named_creation_functor.hpp @@ -38,7 +38,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; diff --git a/boost/interprocess/sync/shm/named_mutex.hpp b/boost/interprocess/sync/shm/named_mutex.hpp index a71eb4fe68..f32fa70044 100644 --- a/boost/interprocess/sync/shm/named_mutex.hpp +++ b/boost/interprocess/sync/shm/named_mutex.hpp @@ -37,7 +37,7 @@ namespace ipcdetail { class named_condition; -//!A mutex with a global name, so it can be found from different +//!A mutex with a global name, so it can be found from different //!processes. This mutex can't be placed in shared memory, and //!each process should have it's own named mutex. class shm_named_mutex @@ -56,7 +56,7 @@ class shm_named_mutex //!Throws interprocess_exception on error. shm_named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global mutex with a name. + //!Opens or creates a global mutex with a name. //!If the mutex is created, this call is equivalent to //!shm_named_mutex(create_only_t, ... ) //!If the mutex is already created, this call is equivalent @@ -85,7 +85,7 @@ class shm_named_mutex //!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 interprocess_mutex, returns false when interprocess_mutex //!is already locked, returns true when success. //!Throws interprocess_exception if a severe error is found bool try_lock(); diff --git a/boost/interprocess/sync/shm/named_recursive_mutex.hpp b/boost/interprocess/sync/shm/named_recursive_mutex.hpp index 461c97eb32..7235571254 100644 --- a/boost/interprocess/sync/shm/named_recursive_mutex.hpp +++ b/boost/interprocess/sync/shm/named_recursive_mutex.hpp @@ -51,7 +51,7 @@ class shm_named_recursive_mutex //!If the recursive_mutex can't be created throws interprocess_exception shm_named_recursive_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global recursive_mutex with a name. + //!Opens or creates a global recursive_mutex with a name. //!If the recursive_mutex is created, this call is equivalent to //!shm_named_recursive_mutex(create_only_t, ... ) //!If the recursive_mutex is already created, this call is equivalent @@ -80,7 +80,7 @@ class shm_named_recursive_mutex //!Throws interprocess_exception if a severe error is found. void lock(); - //!Tries to lock the shm_named_recursive_mutex, returns false when shm_named_recursive_mutex + //!Tries to lock the shm_named_recursive_mutex, returns false when shm_named_recursive_mutex //!is already locked, returns true when success. //!Throws interprocess_exception if a severe error is found. bool try_lock(); diff --git a/boost/interprocess/sync/shm/named_upgradable_mutex.hpp b/boost/interprocess/sync/shm/named_upgradable_mutex.hpp index 338fa98f7d..0975a6ed2b 100644 --- a/boost/interprocess/sync/shm/named_upgradable_mutex.hpp +++ b/boost/interprocess/sync/shm/named_upgradable_mutex.hpp @@ -38,7 +38,7 @@ namespace ipcdetail{ class interprocess_tester; } class named_condition; -//!A upgradable mutex with a global name, so it can be found from different +//!A upgradable mutex with a global name, so it can be found from different //!processes. This mutex can't be placed in shared memory, and //!each process should have it's own named upgradable mutex. class named_upgradable_mutex @@ -52,11 +52,11 @@ class named_upgradable_mutex /// @endcond public: - //!Creates a global upgradable mutex with a name. + //!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, and an initial count. //!If the upgradable mutex is created, this call is equivalent to //!named_upgradable_mutex(create_only_t, ...) //!If the upgradable mutex is already created, this call is equivalent to @@ -95,13 +95,13 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire exclusive ownership of the mutex //! waiting if necessary until no other thread has exclusive, sharable or - //! upgradable ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! upgradable ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. 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. + //!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(); @@ -115,21 +115,21 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire sharable ownership of the mutex //! without waiting. If no other thread has exclusive ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, returns false. + //! 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. + //! 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. + //!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(); @@ -143,7 +143,7 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! without waiting. If no other thread has exclusive or upgradable ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire upgradable ownership immediately returns true. //! If it has to wait, returns false. //!Throws: interprocess_exception on error. @@ -152,66 +152,66 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! waiting if necessary until no other thread has exclusive or upgradable //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The calling thread releases the upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The calling thread releases the upgradable ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable(); //Demotions - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! upgradable ownership. This operation is non-blocking. + //! upgradable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_upgradable(); - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_sharable(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock_sharable(); //Promotions - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires //! exclusive ownership. This operation will block until all threads with - //! sharable ownership release it. + //! sharable ownership release it. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to //! acquire exclusive ownership. This operation will fail if there are threads - //! with sharable ownership, but it will maintain upgradable ownership. + //! with sharable ownership, but it will maintain upgradable ownership. //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to acquire //! exclusive ownership, waiting if necessary until abs_time. This operation will //! fail if there are threads with sharable ownership or timeout reaches, but it - //! will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have sharable ownership of the mutex. + //!Precondition: The thread must have sharable ownership of the mutex. //!Effects: The thread atomically releases sharable ownership and tries to acquire //! exclusive ownership. This operation will fail if there are threads with sharable //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock(); diff --git a/boost/interprocess/sync/spin/condition.hpp b/boost/interprocess/sync/spin/condition.hpp index 5a37d9be2d..55dd79b406 100644 --- a/boost/interprocess/sync/spin/condition.hpp +++ b/boost/interprocess/sync/spin/condition.hpp @@ -110,7 +110,7 @@ inline spin_condition::spin_condition() } inline spin_condition::~spin_condition() -{ +{ //Trivial destructor } @@ -126,15 +126,15 @@ inline void spin_condition::notify_all() inline void spin_condition::notify(boost::uint32_t command) { - //This mutex guarantees that no other thread can enter to the + //This mutex guarantees that no other thread can enter to the //do_timed_wait method logic, so that thread count will be //constant until the function writes a NOTIFY_ALL command. - //It also guarantees that no other notification can be signaled + //It also guarantees that no other notification can be signaled //on this spin_condition before this one ends m_enter_mut.lock(); //Return if there are no waiters - if(!atomic_read32(&m_num_waiters)) { + if(!atomic_read32(&m_num_waiters)) { m_enter_mut.unlock(); return; } @@ -167,18 +167,18 @@ inline bool spin_condition::do_timed_wait template<class InterprocessMutex> inline bool spin_condition::do_timed_wait(bool tout_enabled, - const boost::posix_time::ptime &abs_time, + const boost::posix_time::ptime &abs_time, InterprocessMutex &mut) { boost::posix_time::ptime now = microsec_clock::universal_time(); - + if(tout_enabled){ if(now >= abs_time) return false; } typedef boost::interprocess::scoped_lock<spin_mutex> InternalLock; - //The enter mutex guarantees that while executing a notification, - //no other thread can execute the do_timed_wait method. + //The enter mutex guarantees that while executing a notification, + //no other thread can execute the do_timed_wait method. { //--------------------------------------------------------------- InternalLock lock; @@ -205,8 +205,8 @@ 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 + + //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 @@ -229,8 +229,8 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, //There is an ongoing notification, we will try again later continue; } - //No notification in execution, since enter mutex is locked. - //We will execute time-out logic, so we will decrement count, + //No notification in execution, since enter mutex is locked. + //We will execute time-out logic, so we will decrement count, //release the enter mutex and return false. break; } @@ -253,7 +253,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. @@ -262,8 +262,8 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, break; } else{ - //If it is a NOTIFY_ALL command, all threads should return - //from do_timed_wait function. Decrement wait count. + //If it is a NOTIFY_ALL command, all threads should return + //from do_timed_wait function. Decrement wait count. unlock_enter_mut = 1 == atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters)); //Check if this is the last thread of notify_all waiters //Only the last thread will release the mutex @@ -275,7 +275,7 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, } } - //Unlock the enter mutex if it is a single notification, if this is + //Unlock the enter mutex if it is a single notification, if this is //the last notified thread in a notify_all or a timeout has occurred if(unlock_enter_mut){ m_enter_mut.unlock(); diff --git a/boost/interprocess/sync/spin/mutex.hpp b/boost/interprocess/sync/spin/mutex.hpp index ef0b47d95a..926f7237c0 100644 --- a/boost/interprocess/sync/spin/mutex.hpp +++ b/boost/interprocess/sync/spin/mutex.hpp @@ -45,15 +45,15 @@ class spin_mutex volatile boost::uint32_t m_s; }; -inline spin_mutex::spin_mutex() - : m_s(0) +inline spin_mutex::spin_mutex() + : m_s(0) { //Note that this class is initialized to zero. //So zeroed memory can be interpreted as an //initialized mutex } -inline spin_mutex::~spin_mutex() +inline spin_mutex::~spin_mutex() { //Trivial destructor } @@ -73,7 +73,7 @@ inline void spin_mutex::lock(void) 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; } diff --git a/boost/interprocess/sync/spin/recursive_mutex.hpp b/boost/interprocess/sync/spin/recursive_mutex.hpp index 05ad65eac0..a763f9c72d 100644 --- a/boost/interprocess/sync/spin/recursive_mutex.hpp +++ b/boost/interprocess/sync/spin/recursive_mutex.hpp @@ -68,7 +68,7 @@ class spin_recursive_mutex volatile boost::uint32_t m_s; }; -inline spin_recursive_mutex::spin_recursive_mutex() +inline spin_recursive_mutex::spin_recursive_mutex() : m_nLockCount(0), m_nOwner(ipcdetail::get_invalid_systemwide_thread_id()){} inline spin_recursive_mutex::~spin_recursive_mutex(){} @@ -83,7 +83,7 @@ inline void spin_recursive_mutex::lock() if((unsigned int)(m_nLockCount+1) == 0){ //Overflow, throw an exception throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); - } + } ++m_nLockCount; } else{ @@ -103,7 +103,7 @@ inline bool spin_recursive_mutex::try_lock() if((unsigned int)(m_nLockCount+1) == 0){ //Overflow, throw an exception throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); - } + } ++m_nLockCount; return true; } @@ -129,7 +129,7 @@ inline bool spin_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs if((unsigned int)(m_nLockCount+1) == 0){ //Overflow, throw an exception throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); - } + } ++m_nLockCount; return true; } diff --git a/boost/interprocess/sync/upgradable_lock.hpp b/boost/interprocess/sync/upgradable_lock.hpp index 93c2ed6bc4..fb86374ca1 100644 --- a/boost/interprocess/sync/upgradable_lock.hpp +++ b/boost/interprocess/sync/upgradable_lock.hpp @@ -85,7 +85,7 @@ class upgradable_lock : mp_mutex(&m), m_locked(true) {} - //!Effects: m.try_lock_upgradable(). + //!Effects: m.try_lock_upgradable(). //!Postconditions: mutex() == &m. owns() == the return value of the //! m.try_lock_upgradable() executed within the constructor. //!Notes: The constructor will take upgradable-ownership of the mutex @@ -97,7 +97,7 @@ class upgradable_lock : mp_mutex(&m), m_locked(false) { m_locked = mp_mutex->try_lock_upgradable(); } - //!Effects: m.timed_lock_upgradable(abs_time) + //!Effects: m.timed_lock_upgradable(abs_time) //!Postconditions: mutex() == &m. owns() == the return value of the //! m.timed_lock_upgradable() executed within the constructor. //!Notes: The constructor will take upgradable-ownership of the mutex if it @@ -123,7 +123,7 @@ class upgradable_lock : mp_mutex(0), m_locked(upgr.owns()) { mp_mutex = upgr.release(); } - //!Effects: If scop.owns(), m_.unlock_and_lock_upgradable(). + //!Effects: If scop.owns(), m_.unlock_and_lock_upgradable(). //!Postconditions: mutex() == the value scop.mutex() had before the construction. //! scop.mutex() == 0. owns() == scop.owns() before the constructor. After the //! construction, scop.owns() == false. @@ -146,12 +146,12 @@ class upgradable_lock } //!Effects: If shar.owns() then calls try_unlock_sharable_and_lock_upgradable() - //! on the referenced mutex. + //! on the referenced mutex. //! a)if try_unlock_sharable_and_lock_upgradable() returns true then mutex() - //! obtains the value from shar.release() and owns() is set to true. + //! obtains the value from shar.release() and owns() is set to true. //! b)if try_unlock_sharable_and_lock_upgradable() returns false then shar is //! unaffected and this upgradable_lock construction has the same - //! effects as a default construction. + //! effects as a default construction. //! c)Else shar.owns() is false. mutex() obtains the value from shar.release() //! and owns() is set to false. //!Notes: This construction will not block. It will try to obtain mutex @@ -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); @@ -286,7 +286,7 @@ class upgradable_lock return mut; } - //!Effects: Swaps state with moved lock. + //!Effects: Swaps state with moved lock. //!Throws: Nothing. void swap(upgradable_lock<mutex_type> &other) { diff --git a/boost/interprocess/sync/windows/condition.hpp b/boost/interprocess/sync/windows/condition.hpp index 167b8730c3..9695c21044 100644 --- a/boost/interprocess/sync/windows/condition.hpp +++ b/boost/interprocess/sync/windows/condition.hpp @@ -20,133 +20,8 @@ #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/sync/windows/semaphore.hpp> #include <boost/interprocess/sync/windows/mutex.hpp> -#include <boost/cstdint.hpp> -#include <limits> - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -// -// Condition variable algorithm taken from pthreads-win32 discussion. -// -// The algorithm was developed by Alexander Terekhov in colaboration with -// Louis Thomas. -// -// Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL -// -// semBlockLock - bin.semaphore -// semBlockQueue - semaphore -// mtxExternal - mutex or CS -// mtxUnblockLock - mutex or CS -// nWaitersGone - int -// nWaitersBlocked - int -// nWaitersToUnblock - int -// -// wait( timeout ) { -// -// [auto: register int result ] // error checking omitted -// [auto: register int nSignalsWasLeft ] -// [auto: register int nWaitersWasGone ] -// -// sem_wait( semBlockLock ); -// nWaitersBlocked++; -// sem_post( semBlockLock ); -// -// unlock( mtxExternal ); -// bTimedOut = sem_wait( semBlockQueue,timeout ); -// -// lock( mtxUnblockLock ); -// if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) { -// if ( bTimedOut ) { // timeout (or canceled) -// if ( 0 != nWaitersBlocked ) { -// nWaitersBlocked--; -// } -// else { -// nWaitersGone++; // count spurious wakeups. -// } -// } -// if ( 0 == --nWaitersToUnblock ) { -// if ( 0 != nWaitersBlocked ) { -// sem_post( semBlockLock ); // open the gate. -// nSignalsWasLeft = 0; // do not open the gate -// // below again. -// } -// else if ( 0 != (nWaitersWasGone = nWaitersGone) ) { -// nWaitersGone = 0; -// } -// } -// } -// else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or -// // spurious semaphore :-) -// sem_wait( semBlockLock ); -// nWaitersBlocked -= nWaitersGone; // something is going on here -// // - test of timeouts? :-) -// sem_post( semBlockLock ); -// nWaitersGone = 0; -// } -// unlock( mtxUnblockLock ); -// -// if ( 1 == nSignalsWasLeft ) { -// if ( 0 != nWaitersWasGone ) { -// // sem_adjust( semBlockQueue,-nWaitersWasGone ); -// while ( nWaitersWasGone-- ) { -// sem_wait( semBlockQueue ); // better now than spurious later -// } -// } sem_post( semBlockLock ); // open the gate -// } -// -// lock( mtxExternal ); -// -// return ( bTimedOut ) ? ETIMEOUT : 0; -// } -// -// signal(bAll) { -// -// [auto: register int result ] -// [auto: register int nSignalsToIssue] -// -// lock( mtxUnblockLock ); -// -// if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! -// if ( 0 == nWaitersBlocked ) { // NO-OP -// return unlock( mtxUnblockLock ); -// } -// if (bAll) { -// nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked; -// nWaitersBlocked = 0; -// } -// else { -// nSignalsToIssue = 1; -// nWaitersToUnblock++; -// nWaitersBlocked--; -// } -// } -// else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! -// sem_wait( semBlockLock ); // close the gate -// if ( 0 != nWaitersGone ) { -// nWaitersBlocked -= nWaitersGone; -// nWaitersGone = 0; -// } -// if (bAll) { -// nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked; -// nWaitersBlocked = 0; -// } -// else { -// nSignalsToIssue = nWaitersToUnblock = 1; -// nWaitersBlocked--; -// } -// } -// else { // NO-OP -// return unlock( mtxUnblockLock ); -// } -// -// unlock( mtxUnblockLock ); -// sem_post( semBlockQueue,nSignalsToIssue ); -// return result; -// } -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// +#include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp> + namespace boost { namespace interprocess { @@ -156,6 +31,7 @@ class windows_condition { windows_condition(const windows_condition &); windows_condition &operator=(const windows_condition &); + public: windows_condition(); ~windows_condition(); @@ -217,162 +93,71 @@ class windows_condition private: - template<class InterprocessMutex> - bool do_timed_wait(bool timeout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut); - void do_signal (bool broadcast); - - boost::int32_t m_nwaiters_blocked; - boost::int32_t m_nwaiters_gone; - boost::int32_t m_nwaiters_to_unblock; - windows_semaphore m_sem_block_queue; - windows_semaphore m_sem_block_lock; - windows_mutex m_mtx_unblock_lock; + struct condition_data + { + typedef boost::int32_t integer_type; + typedef windows_semaphore semaphore_type; + typedef windows_mutex mutex_type; + + condition_data() + : m_nwaiters_blocked(0) + , m_nwaiters_gone(0) + , m_nwaiters_to_unblock(0) + , m_sem_block_queue(0) + , m_sem_block_lock(1) + , m_mtx_unblock_lock() + {} + + integer_type &get_nwaiters_blocked() + { return m_nwaiters_blocked; } + + integer_type &get_nwaiters_gone() + { return m_nwaiters_gone; } + + integer_type &get_nwaiters_to_unblock() + { return m_nwaiters_to_unblock; } + + semaphore_type &get_sem_block_queue() + { return m_sem_block_queue; } + + semaphore_type &get_sem_block_lock() + { return m_sem_block_lock; } + + mutex_type &get_mtx_unblock_lock() + { return m_mtx_unblock_lock; } + + boost::int32_t m_nwaiters_blocked; + boost::int32_t m_nwaiters_gone; + boost::int32_t m_nwaiters_to_unblock; + windows_semaphore m_sem_block_queue; + windows_semaphore m_sem_block_lock; + windows_mutex m_mtx_unblock_lock; + } m_condition_data; + + typedef condition_algorithm_8a<condition_data> algorithm_type; }; inline windows_condition::windows_condition() - : m_nwaiters_blocked(0) - , m_nwaiters_gone(0) - , m_nwaiters_to_unblock(0) - , m_sem_block_queue(0) - , m_sem_block_lock(1) - , m_mtx_unblock_lock() + : m_condition_data() {} inline windows_condition::~windows_condition() {} inline void windows_condition::notify_one() -{ this->do_signal(false); } +{ algorithm_type::signal(m_condition_data, false); } inline void windows_condition::notify_all() -{ this->do_signal(true); } - -inline void windows_condition::do_signal(bool broadcast) -{ - boost::int32_t nsignals_to_issue; - - { - scoped_lock<windows_mutex> locker(m_mtx_unblock_lock); - - if ( 0 != m_nwaiters_to_unblock ) { // the gate is closed!!! - if ( 0 == m_nwaiters_blocked ) { // NO-OP - //locker's destructor triggers m_mtx_unblock_lock.unlock() - return; - } - if (broadcast) { - m_nwaiters_to_unblock += nsignals_to_issue = m_nwaiters_blocked; - m_nwaiters_blocked = 0; - } - else { - nsignals_to_issue = 1; - m_nwaiters_to_unblock++; - m_nwaiters_blocked--; - } - } - else if ( m_nwaiters_blocked > m_nwaiters_gone ) { // HARMLESS RACE CONDITION! - m_sem_block_lock.wait(); // close the gate - if ( 0 != m_nwaiters_gone ) { - m_nwaiters_blocked -= m_nwaiters_gone; - m_nwaiters_gone = 0; - } - if (broadcast) { - nsignals_to_issue = m_nwaiters_to_unblock = m_nwaiters_blocked; - m_nwaiters_blocked = 0; - } - else { - nsignals_to_issue = m_nwaiters_to_unblock = 1; - m_nwaiters_blocked--; - } - } - else { // NO-OP - //locker's destructor triggers m_mtx_unblock_lock.unlock() - return; - } - //locker's destructor triggers m_mtx_unblock_lock.unlock() - } - m_sem_block_queue.post(nsignals_to_issue); -} +{ algorithm_type::signal(m_condition_data, true); } template<class InterprocessMutex> inline void windows_condition::do_wait(InterprocessMutex &mut) -{ this->do_timed_wait(false, boost::posix_time::ptime(), 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 this->do_timed_wait(true, abs_time, mut); } - -template<class InterprocessMutex> -inline bool windows_condition::do_timed_wait - (bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mtxExternal) -{ - //Initialize to avoid warnings - boost::int32_t nsignals_was_left = 0; - boost::int32_t nwaiters_was_gone = 0; - - m_sem_block_lock.wait(); - ++m_nwaiters_blocked; - m_sem_block_lock.post(); - - struct scoped_unlock - { - InterprocessMutex & mut; - scoped_unlock(InterprocessMutex & m) - : mut(m) - { m.unlock(); } - - ~scoped_unlock() - { mut.lock(); } - } unlocker(mtxExternal); - - - bool bTimedOut = tout_enabled ? !m_sem_block_queue.timed_wait(abs_time) : (m_sem_block_queue.wait(), false); - - { - scoped_lock<windows_mutex> locker(m_mtx_unblock_lock); - if ( 0 != (nsignals_was_left = m_nwaiters_to_unblock) ) { - if ( bTimedOut ) { // timeout (or canceled) - if ( 0 != m_nwaiters_blocked ) { - m_nwaiters_blocked--; - } - else { - m_nwaiters_gone++; // count spurious wakeups. - } - } - if ( 0 == --m_nwaiters_to_unblock ) { - if ( 0 != m_nwaiters_blocked ) { - m_sem_block_lock.post(); // open the gate. - nsignals_was_left = 0; // do not open the gate below again. - } - else if ( 0 != (nwaiters_was_gone = m_nwaiters_gone) ) { - m_nwaiters_gone = 0; - } - } - } - else if ( (std::numeric_limits<boost::int32_t>::max)()/2 - == ++m_nwaiters_gone ) { // timeout/canceled or spurious semaphore :-) - m_sem_block_lock.wait(); - m_nwaiters_blocked -= m_nwaiters_gone; // something is going on here - test of timeouts? :-) - m_sem_block_lock.post(); - m_nwaiters_gone = 0; - } - //locker's destructor triggers m_mtx_unblock_lock.unlock() - } - - if ( 1 == nsignals_was_left ) { - if ( 0 != nwaiters_was_gone ) { - // sem_adjust( m_sem_block_queue,-nwaiters_was_gone ); - while ( nwaiters_was_gone-- ) { - m_sem_block_queue.wait(); // better now than spurious later - } - } - m_sem_block_lock.post(); // open the gate - } - - //mtxExternal.lock(); called from unlocker - - return ( bTimedOut ) ? false : true; -} +{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); } } //namespace ipcdetail } //namespace interprocess diff --git a/boost/interprocess/sync/windows/mutex.hpp b/boost/interprocess/sync/windows/mutex.hpp index 5eca522339..477acd396a 100644 --- a/boost/interprocess/sync/windows/mutex.hpp +++ b/boost/interprocess/sync/windows/mutex.hpp @@ -19,8 +19,9 @@ #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> #include <boost/interprocess/detail/win32_api.hpp> -#include <boost/interprocess/detail/intermodule_singleton.hpp> +#include <boost/interprocess/detail/windows_intermodule_singleton.hpp> #include <boost/interprocess/sync/windows/sync_utils.hpp> +#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp> #include <boost/interprocess/exceptions.hpp> @@ -47,85 +48,61 @@ class windows_mutex const sync_id id_; }; -inline windows_mutex::windows_mutex() - : id_() +inline windows_mutex::windows_mutex() + : id_(this) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); //Create mutex with the initial count bool open_or_created; - handles.obtain_mutex(this->id_, &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); (void)open_or_created; } -inline windows_mutex::~windows_mutex() +inline windows_mutex::~windows_mutex() { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); handles.destroy_handle(this->id_); } inline void windows_mutex::lock(void) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); //This can throw - void *hnd = handles.obtain_mutex(this->id_); - unsigned long ret = winapi::wait_for_single_object(hnd, winapi::infinite_time); - if(ret == winapi::wait_failed){ - error_info err(winapi::get_last_error()); - throw interprocess_exception(err); - } + winapi_mutex_functions mut(handles.obtain_mutex(this->id_)); + mut.lock(); } inline bool windows_mutex::try_lock(void) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); //This can throw - void *hnd = handles.obtain_mutex(this->id_); - unsigned long ret = winapi::wait_for_single_object(hnd, 0); - if(ret == winapi::wait_failed){ - error_info err(winapi::get_last_error()); - throw interprocess_exception(err); - } - return ret != winapi::wait_timeout; + winapi_mutex_functions mut(handles.obtain_mutex(this->id_)); + return mut.try_lock(); } inline bool windows_mutex::timed_lock(const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - boost::posix_time::ptime now - = boost::posix_time::microsec_clock::universal_time(); - - unsigned long ms = (unsigned long)(abs_time-now).total_milliseconds(); sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); //This can throw - void *hnd = handles.obtain_mutex(this->id_); - unsigned long ret = winapi::wait_for_single_object(hnd, ms); - if(ret == winapi::wait_failed){ - error_info err(winapi::get_last_error()); - throw interprocess_exception(err); - } - return ret != winapi::wait_timeout; + winapi_mutex_functions mut(handles.obtain_mutex(this->id_)); + return mut.timed_lock(abs_time); } inline void windows_mutex::unlock(void) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); //This can throw - void *hnd = handles.obtain_mutex(this->id_); - int ret = winapi::release_mutex(hnd); - (void)ret; - assert(ret); + winapi_mutex_functions mut(handles.obtain_mutex(this->id_)); + return mut.unlock(); } } //namespace ipcdetail { diff --git a/boost/interprocess/sync/windows/named_condition.hpp b/boost/interprocess/sync/windows/named_condition.hpp new file mode 100644 index 0000000000..403e826178 --- /dev/null +++ b/boost/interprocess/sync/windows/named_condition.hpp @@ -0,0 +1,334 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/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 +{ + /// @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); +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP diff --git a/boost/interprocess/sync/windows/named_mutex.hpp b/boost/interprocess/sync/windows/named_mutex.hpp new file mode 100644 index 0000000000..8ea6b3e1e4 --- /dev/null +++ b/boost/interprocess/sync/windows/named_mutex.hpp @@ -0,0 +1,175 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/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/sync_utils.hpp> +#include <boost/interprocess/sync/windows/named_sync.hpp> +#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp> +#include <boost/interprocess/errors.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <limits> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + + + +class windows_named_mutex +{ + /// @cond + + //Non-copyable + windows_named_mutex(); + windows_named_mutex(const windows_named_mutex &); + windows_named_mutex &operator=(const windows_named_mutex &); + /// @endcond + + public: + windows_named_mutex(create_only_t, const char *name, const permissions &perm = permissions()); + + windows_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); + + windows_named_mutex(open_only_t, const char *name); + + ~windows_named_mutex(); + + void unlock(); + void lock(); + bool try_lock(); + bool timed_lock(const boost::posix_time::ptime &abs_time); + + static bool remove(const char *name); + + /// @cond + private: + friend class interprocess_tester; + void dont_close_on_destruction(); + winapi_mutex_wrapper m_mtx_wrapper; + windows_named_sync m_named_sync; + + class named_mut_callbacks : public windows_named_sync_interface + { + public: + named_mut_callbacks(winapi_mutex_wrapper &mtx_wrapper) + : m_mtx_wrapper(mtx_wrapper) + {} + + virtual std::size_t get_data_size() const + { return 0u; } + + virtual const void *buffer_with_init_data_to_file() + { return 0; } + + virtual const void *buffer_with_final_data_to_file() + { return 0; } + + virtual void *buffer_to_store_init_data_from_file() + { return 0; } + + virtual bool open(create_enum_t, const char *id_name) + { + std::string aux_str = "Global\\bipc.mut."; + aux_str += id_name; + // + permissions mut_perm; + mut_perm.set_unrestricted(); + return m_mtx_wrapper.open_or_create(aux_str.c_str(), mut_perm); + } + + virtual void close() + { + m_mtx_wrapper.close(); + } + + virtual ~named_mut_callbacks() + {} + + private: + winapi_mutex_wrapper& m_mtx_wrapper; + }; + /// @endcond +}; + +inline windows_named_mutex::~windows_named_mutex() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.close(callbacks); +} + +inline void windows_named_mutex::dont_close_on_destruction() +{} + +inline windows_named_mutex::windows_named_mutex + (create_only_t, const char *name, const permissions &perm) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); +} + +inline windows_named_mutex::windows_named_mutex + (open_or_create_t, const char *name, const permissions &perm) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); +} + +inline windows_named_mutex::windows_named_mutex(open_only_t, const char *name) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); +} + +inline void windows_named_mutex::unlock() +{ + m_mtx_wrapper.unlock(); +} + +inline void windows_named_mutex::lock() +{ + m_mtx_wrapper.lock(); +} + +inline bool windows_named_mutex::try_lock() +{ + return m_mtx_wrapper.try_lock(); +} + +inline bool windows_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time) +{ + return m_mtx_wrapper.timed_lock(abs_time); +} + +inline bool windows_named_mutex::remove(const char *name) +{ + return windows_named_sync::remove(name); +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP
\ No newline at end of file diff --git a/boost/interprocess/sync/windows/named_recursive_mutex.hpp b/boost/interprocess/sync/windows/named_recursive_mutex.hpp new file mode 100644 index 0000000000..cb2ef79ac1 --- /dev/null +++ b/boost/interprocess/sync/windows/named_recursive_mutex.hpp @@ -0,0 +1,58 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP +#define BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/sync/windows/named_mutex.hpp> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + + +class windows_named_recursive_mutex + //Windows mutexes based on CreateMutex are already recursive... + : public windows_named_mutex +{ + /// @cond + + //Non-copyable + windows_named_recursive_mutex(); + windows_named_recursive_mutex(const windows_named_mutex &); + windows_named_recursive_mutex &operator=(const windows_named_mutex &); + /// @endcond + + public: + windows_named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions()) + : windows_named_mutex(create_only_t(), name, perm) + {} + + windows_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()) + : windows_named_mutex(open_or_create_t(), name, perm) + {} + + windows_named_recursive_mutex(open_only_t, const char *name) + : windows_named_mutex(open_only_t(), name) + {} +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP diff --git a/boost/interprocess/sync/windows/named_semaphore.hpp b/boost/interprocess/sync/windows/named_semaphore.hpp new file mode 100644 index 0000000000..8f48d4df96 --- /dev/null +++ b/boost/interprocess/sync/windows/named_semaphore.hpp @@ -0,0 +1,178 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/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> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + + + +class windows_named_semaphore +{ + /// @cond + + //Non-copyable + windows_named_semaphore(); + windows_named_semaphore(const windows_named_semaphore &); + windows_named_semaphore &operator=(const windows_named_semaphore &); + /// @endcond + + public: + windows_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); + + windows_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); + + windows_named_semaphore(open_only_t, const char *name); + + ~windows_named_semaphore(); + + void post(); + void wait(); + bool try_wait(); + bool timed_wait(const boost::posix_time::ptime &abs_time); + + static bool remove(const char *name); + + /// @cond + private: + friend class interprocess_tester; + void dont_close_on_destruction(); + winapi_semaphore_wrapper m_sem_wrapper; + windows_named_sync m_named_sync; + + class named_sem_callbacks : public windows_named_sync_interface + { + public: + typedef __int64 sem_count_t; + named_sem_callbacks(winapi_semaphore_wrapper &sem_wrapper, sem_count_t sem_cnt) + : m_sem_wrapper(sem_wrapper), m_sem_count(sem_cnt) + {} + + virtual std::size_t get_data_size() const + { return sizeof(sem_count_t); } + + virtual const void *buffer_with_final_data_to_file() + { return &m_sem_count; } + + virtual const void *buffer_with_init_data_to_file() + { return &m_sem_count; } + + virtual void *buffer_to_store_init_data_from_file() + { return &m_sem_count; } + + virtual bool open(create_enum_t, const char *id_name) + { + std::string aux_str = "Global\\bipc.sem."; + aux_str += id_name; + // + permissions sem_perm; + sem_perm.set_unrestricted(); + bool created; + return m_sem_wrapper.open_or_create + ( aux_str.c_str(), static_cast<long>(m_sem_count) + , winapi_semaphore_wrapper::MaxCount, sem_perm, created); + } + + virtual void close() + { + m_sem_wrapper.close(); + } + + virtual ~named_sem_callbacks() + {} + + private: + sem_count_t m_sem_count; + winapi_semaphore_wrapper& m_sem_wrapper; + }; + + /// @endcond +}; + +inline windows_named_semaphore::~windows_named_semaphore() +{ + named_sem_callbacks callbacks(m_sem_wrapper, m_sem_wrapper.value()); + m_named_sync.close(callbacks); +} + +inline void windows_named_semaphore::dont_close_on_destruction() +{} + +inline windows_named_semaphore::windows_named_semaphore + (create_only_t, const char *name, unsigned int initial_count, const permissions &perm) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, initial_count); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); +} + +inline windows_named_semaphore::windows_named_semaphore + (open_or_create_t, const char *name, unsigned int initial_count, const permissions &perm) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, initial_count); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); +} + +inline windows_named_semaphore::windows_named_semaphore(open_only_t, const char *name) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, 0); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); +} + +inline void windows_named_semaphore::post() +{ + m_sem_wrapper.post(); +} + +inline void windows_named_semaphore::wait() +{ + m_sem_wrapper.wait(); +} + +inline bool windows_named_semaphore::try_wait() +{ + return m_sem_wrapper.try_wait(); +} + +inline bool windows_named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time) +{ + return m_sem_wrapper.timed_wait(abs_time); +} + +inline bool windows_named_semaphore::remove(const char *name) +{ + return windows_named_sync::remove(name); +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP diff --git a/boost/interprocess/sync/windows/named_sync.hpp b/boost/interprocess/sync/windows/named_sync.hpp new file mode 100644 index 0000000000..41f299f8eb --- /dev/null +++ b/boost/interprocess/sync/windows/named_sync.hpp @@ -0,0 +1,215 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/creation_tags.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/detail/tmp_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> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class windows_named_sync_interface +{ + public: + virtual std::size_t get_data_size() const = 0; + virtual const void *buffer_with_final_data_to_file() = 0; + virtual const void *buffer_with_init_data_to_file() = 0; + virtual void *buffer_to_store_init_data_from_file() = 0; + virtual bool open(create_enum_t creation_type, const char *id_name) = 0; + virtual void close() = 0; + virtual ~windows_named_sync_interface() = 0; +}; + +inline windows_named_sync_interface::~windows_named_sync_interface() +{} + +class windows_named_sync +{ + /// @cond + + //Non-copyable + windows_named_sync(const windows_named_sync &); + windows_named_sync &operator=(const windows_named_sync &); + /// @endcond + + public: + windows_named_sync(); + void open_or_create(create_enum_t creation_type, const char *name, const permissions &perm, windows_named_sync_interface &sync_interface); + void close(windows_named_sync_interface &sync_interface); + + static bool remove(const char *name); + + /// @cond + private: + void *m_file_hnd; + + /// @endcond +}; + +inline windows_named_sync::windows_named_sync() + : m_file_hnd(winapi::invalid_handle_value) +{} + +inline void windows_named_sync::close(windows_named_sync_interface &sync_interface) +{ + const std::size_t buflen = sync_interface.get_data_size(); + const std::size_t sizeof_file_info = sizeof(sync_id::internal_type) + buflen; + winapi::interprocess_overlapped overlapped; + if(winapi::lock_file_ex + (m_file_hnd, winapi::lockfile_exclusive_lock, 0, sizeof_file_info, 0, &overlapped)){ + if(winapi::set_file_pointer_ex(m_file_hnd, sizeof(sync_id::internal_type), 0, winapi::file_begin)){ + const void *buf = sync_interface.buffer_with_final_data_to_file(); + + unsigned long written_or_read = 0; + if(winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0)){ + //... + } + } + } + sync_interface.close(); + if(m_file_hnd != winapi::invalid_handle_value){ + winapi::close_handle(m_file_hnd); + m_file_hnd = winapi::invalid_handle_value; + } +} + +inline void windows_named_sync::open_or_create + ( create_enum_t creation_type + , const char *name + , const permissions &perm + , windows_named_sync_interface &sync_interface) +{ + std::string aux_str(name); + m_file_hnd = winapi::invalid_handle_value; + //Use a file to emulate POSIX lifetime semantics. After this logic + //we'll obtain the ID of the native handle to open in aux_str + { + create_tmp_and_clean_old_and_get_filename(name, aux_str); + //Create a file with required permissions. + m_file_hnd = winapi::create_file + ( aux_str.c_str() + , winapi::generic_read | winapi::generic_write + , creation_type == DoOpen ? winapi::open_existing : + (creation_type == DoCreate ? winapi::create_new : winapi::open_always) + , 0 + , (winapi::interprocess_security_attributes*)perm.get_permissions()); + + //Obtain OS error in case something has failed + error_info err; + bool success = false; + if(m_file_hnd != winapi::invalid_handle_value){ + //Now lock the file + const std::size_t buflen = sync_interface.get_data_size(); + typedef __int64 unique_id_type; + const std::size_t sizeof_file_info = sizeof(unique_id_type) + buflen; + winapi::interprocess_overlapped overlapped; + if(winapi::lock_file_ex + (m_file_hnd, winapi::lockfile_exclusive_lock, 0, sizeof_file_info, 0, &overlapped)){ + __int64 filesize = 0; + //Obtain the unique id to open the native semaphore. + //If file size was created + if(winapi::get_file_size(m_file_hnd, filesize)){ + unsigned long written_or_read = 0; + unique_id_type unique_id_val; + if(static_cast<std::size_t>(filesize) != sizeof_file_info){ + winapi::set_end_of_file(m_file_hnd); + winapi::query_performance_counter(&unique_id_val); + const void *buf = sync_interface.buffer_with_init_data_to_file(); + //Write unique ID in file. This ID will be used to calculate the semaphore name + if(winapi::write_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) && + written_or_read == sizeof(unique_id_val) && + winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0) && + written_or_read == buflen ){ + success = true; + } + winapi::get_file_size(m_file_hnd, filesize); + assert(std::size_t(filesize) == sizeof_file_info); + } + else{ + void *buf = sync_interface.buffer_to_store_init_data_from_file(); + if(winapi::read_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) && + written_or_read == sizeof(unique_id_val) && + winapi::read_file(m_file_hnd, buf, buflen, &written_or_read, 0) && + written_or_read == buflen ){ + success = true; + } + } + if(success){ + //Now create a global semaphore name based on the unique id + char unique_id_name[sizeof(unique_id_val)*2+1]; + std::size_t name_suffix_length = sizeof(unique_id_name); + bytes_to_str(&unique_id_val, sizeof(unique_id_val), &unique_id_name[0], name_suffix_length); + success = sync_interface.open(creation_type, unique_id_name); + } + } + + //Obtain OS error in case something has failed + err = system_error_code(); + + //If this fails we have no possible rollback so don't check the return + if(!winapi::unlock_file_ex(m_file_hnd, 0, sizeof_file_info, 0, &overlapped)){ + err = system_error_code(); + } + } + else{ + //Obtain OS error in case something has failed + err = system_error_code(); + } + } + else{ + err = system_error_code(); + } + + if(!success){ + if(m_file_hnd != winapi::invalid_handle_value){ + winapi::close_handle(m_file_hnd); + m_file_hnd = winapi::invalid_handle_value; + } + //Throw as something went wrong + throw interprocess_exception(err); + } + } +} + +inline bool windows_named_sync::remove(const char *name) +{ + try{ + //Make sure a temporary path is created for shared memory + std::string semfile; + ipcdetail::tmp_filename(name, semfile); + return winapi::unlink_file(semfile.c_str()); + } + catch(...){ + return false; + } +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP diff --git a/boost/interprocess/sync/windows/semaphore.hpp b/boost/interprocess/sync/windows/semaphore.hpp index d5835ceec7..af336df48a 100644 --- a/boost/interprocess/sync/windows/semaphore.hpp +++ b/boost/interprocess/sync/windows/semaphore.hpp @@ -19,8 +19,9 @@ #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> #include <boost/interprocess/detail/win32_api.hpp> -#include <boost/interprocess/detail/intermodule_singleton.hpp> +#include <boost/interprocess/detail/windows_intermodule_singleton.hpp> #include <boost/interprocess/sync/windows/sync_utils.hpp> +#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp> #include <boost/interprocess/exceptions.hpp> @@ -46,11 +47,11 @@ class windows_semaphore const sync_id id_; }; -inline windows_semaphore::windows_semaphore(unsigned int initialCount) - : id_() +inline windows_semaphore::windows_semaphore(unsigned int initialCount) + : id_(this) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); //Force smeaphore creation with the initial count bool open_or_created; handles.obtain_semaphore(this->id_, initialCount, &open_or_created); @@ -60,72 +61,46 @@ inline windows_semaphore::windows_semaphore(unsigned int initialCount) (void)open_or_created; } -inline windows_semaphore::~windows_semaphore() +inline windows_semaphore::~windows_semaphore() { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); handles.destroy_handle(this->id_); } inline void windows_semaphore::wait(void) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); //This can throw - void *hnd = handles.obtain_semaphore(this->id_, 0); - unsigned long ret = winapi::wait_for_single_object(hnd, winapi::infinite_time); - if(ret == winapi::wait_failed){ - error_info err(winapi::get_last_error()); - throw interprocess_exception(err); - } + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0)); + sem.wait(); } inline bool windows_semaphore::try_wait(void) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); //This can throw - void *hnd = handles.obtain_semaphore(this->id_, 0); - unsigned long ret = winapi::wait_for_single_object(hnd, 0); - if(ret == winapi::wait_failed){ - error_info err(winapi::get_last_error()); - throw interprocess_exception(err); - } - return ret != winapi::wait_timeout; + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0)); + return sem.try_wait(); } inline bool windows_semaphore::timed_wait(const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->wait(); - return true; - } - boost::posix_time::ptime now - = boost::posix_time::microsec_clock::universal_time(); - - unsigned long ms = (unsigned long)(abs_time-now).total_milliseconds(); sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); //This can throw - void *hnd = handles.obtain_semaphore(this->id_, 0); - unsigned long ret = winapi::wait_for_single_object(hnd, ms); - if(ret == winapi::wait_failed){ - error_info err(winapi::get_last_error()); - throw interprocess_exception(err); - } - return ret != winapi::wait_timeout; + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0)); + return sem.timed_wait(abs_time); } inline void windows_semaphore::post(long release_count) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); - //This can throw - void *hnd = handles.obtain_semaphore(this->id_, 0); - long prev_count; - int ret = winapi::release_semaphore(hnd, release_count, &prev_count); - (void)ret; - assert(ret); + windows_intermodule_singleton<sync_handles>::get(); + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0)); + sem.post(release_count); } } //namespace ipcdetail { diff --git a/boost/interprocess/sync/windows/sync_utils.hpp b/boost/interprocess/sync/windows/sync_utils.hpp index 89c4aeda0b..0281da1266 100644 --- a/boost/interprocess/sync/windows/sync_utils.hpp +++ b/boost/interprocess/sync/windows/sync_utils.hpp @@ -21,7 +21,10 @@ #include <boost/interprocess/sync/spin/mutex.hpp> #include <boost/interprocess/exceptions.hpp> #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> +#include <boost/container/map.hpp> #include <cstddef> namespace boost { @@ -32,6 +35,7 @@ inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *ou { const std::size_t need_mem = mem_length*2+1; if(out_length < need_mem){ + out_length = need_mem; return false; } @@ -49,40 +53,57 @@ inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *ou return true; } -struct sync_id +class sync_id { - sync_id() - { winapi::query_performance_counter(&rand); } + public: + typedef __int64 internal_type; + sync_id(const void *map_addr) + : map_addr_(map_addr) + { winapi::query_performance_counter(&rand_); } + + explicit sync_id(internal_type val, const void *map_addr) + : map_addr_(map_addr) + { rand_ = val; } + + const internal_type &internal_pod() const + { return rand_; } - __int64 rand; + internal_type &internal_pod() + { return rand_; } + + const void *map_addr() const + { return map_addr_; } friend std::size_t hash_value(const sync_id &m) - { return boost::hash_value(m.rand); } + { return boost::hash_value(m.rand_); } friend bool operator==(const sync_id &l, const sync_id &r) - { return l.rand == r.rand; } -}; -/* -#define BOOST_NO_LONG_LONG ss + { return l.rand_ == r.rand_ && l.map_addr_ == r.map_addr_; } -#if defined(BOOST_NO_LONG_LONG) + private: + internal_type rand_; + const void * const map_addr_; +}; -#error "defined(BOOST_NO_LONG_LONG)" -#else -#error "NOT defined(BOOST_NO_LONG_LONG)" -#endif -*/ class sync_handles { public: enum type { MUTEX, SEMAPHORE }; private: - typedef boost::unordered_map<sync_id, void*> map_type; + struct address_less + { + bool operator()(sync_id const * const l, sync_id const * const r) const + { return l->map_addr() < r->map_addr(); } + }; + + typedef boost::unordered_map<sync_id, void*> umap_type; + typedef boost::container::map<const sync_id*, umap_type::iterator, address_less> map_type; static const std::size_t LengthOfGlobal = sizeof("Global\\boost.ipc")-1; static const std::size_t StrSize = LengthOfGlobal + (sizeof(sync_id)*2+1); typedef char NameBuf[StrSize]; + void fill_name(NameBuf &name, const sync_id &id) { const char *n = "Global\\boost.ipc"; @@ -92,13 +113,12 @@ class sync_handles ++i; } while(n[i]); std::size_t len = sizeof(NameBuf) - LengthOfGlobal; - bytes_to_str(&id.rand, sizeof(id.rand), &name[LengthOfGlobal], len); + bytes_to_str(&id.internal_pod(), sizeof(id.internal_pod()), &name[LengthOfGlobal], len); } - void erase_and_throw_if_error(void *hnd_val, const sync_id &id) + void throw_if_error(void *hnd_val) { if(!hnd_val){ - map_.erase(id); error_info err(winapi::get_last_error()); throw interprocess_exception(err); } @@ -108,27 +128,36 @@ class sync_handles { NameBuf name; fill_name(name, id); - void *hnd_val = winapi::open_or_create_semaphore - (name, (long)initial_count, (long)(((unsigned long)(-1))>>1), unrestricted_security.get_attributes()); - erase_and_throw_if_error(hnd_val, id); - return hnd_val; + permissions unrestricted_security; + unrestricted_security.set_unrestricted(); + winapi_semaphore_wrapper sem_wrapper; + bool created; + sem_wrapper.open_or_create + (name, (long)initial_count, winapi_semaphore_wrapper::MaxCount, unrestricted_security, created); + throw_if_error(sem_wrapper.handle()); + return sem_wrapper.release(); } void* open_or_create_mutex(const sync_id &id) { NameBuf name; fill_name(name, id); - void *hnd_val = winapi::open_or_create_mutex - (name, false, unrestricted_security.get_attributes()); - erase_and_throw_if_error(hnd_val, id); - return hnd_val; + permissions unrestricted_security; + unrestricted_security.set_unrestricted(); + winapi_mutex_wrapper mtx_wrapper; + mtx_wrapper.open_or_create(name, unrestricted_security); + throw_if_error(mtx_wrapper.handle()); + return mtx_wrapper.release(); } public: void *obtain_mutex(const sync_id &id, bool *popen_created = 0) { + umap_type::value_type v(id, (void*)0); scoped_lock<spin_mutex> lock(mtx_); - void *&hnd_val = map_[id]; + umap_type::iterator it = umap_.insert(v).first; + map_[&it->first] = it; + void *&hnd_val = it->second; if(!hnd_val){ hnd_val = open_or_create_mutex(id); if(popen_created) *popen_created = true; @@ -138,8 +167,11 @@ class sync_handles void *obtain_semaphore(const sync_id &id, unsigned int initial_count, bool *popen_created = 0) { + umap_type::value_type v(id, (void*)0); scoped_lock<spin_mutex> lock(mtx_); - void *&hnd_val = map_[id]; + umap_type::iterator it = umap_.insert(v).first; + map_[&it->first] = it; + void *&hnd_val = it->second; if(!hnd_val){ hnd_val = open_or_create_semaphore(id, initial_count); if(popen_created) *popen_created = true; @@ -150,16 +182,35 @@ class sync_handles void destroy_handle(const sync_id &id) { scoped_lock<spin_mutex> lock(mtx_); - map_type::iterator it = map_.find(id); - if(it != map_.end()){ + umap_type::iterator it = umap_.find(id); + umap_type::iterator itend = umap_.end(); + + if(it != itend){ winapi::close_handle(it->second); - map_.erase(it); + const map_type::key_type &k = &it->first; + map_.erase(k); + umap_.erase(it); + } + } + + 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); + 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]; + winapi::close_handle(hnd); + umap_.erase(*itlow->first); + itlow = map_.erase(itlow); } } private: - winapi::interprocess_all_access_security unrestricted_security; spin_mutex mtx_; + umap_type umap_; map_type map_; }; diff --git a/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp b/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp new file mode 100644 index 0000000000..0be96011cf --- /dev/null +++ b/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp @@ -0,0 +1,163 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (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_MUTEX_WRAPPER_HPP +#define BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/creation_tags.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/detail/win32_api.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/errors.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <limits> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class winapi_mutex_functions +{ + /// @cond + + //Non-copyable + winapi_mutex_functions(const winapi_mutex_functions &); + winapi_mutex_functions &operator=(const winapi_mutex_functions &); + /// @endcond + + public: + winapi_mutex_functions(void *mtx_hnd) + : m_mtx_hnd(mtx_hnd) + {} + + void unlock() + { + 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); + } + } + + 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); + } + } + + bool timed_lock(const boost::posix_time::ptime &abs_time) + { + if(abs_time == boost::posix_time::pos_infin){ + this->lock(); + return true; + } + + 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 + protected: + void *m_mtx_hnd; + /// @endcond +}; + +//Swappable mutex wrapper +class winapi_mutex_wrapper + : public winapi_mutex_functions +{ + /// @cond + + //Non-copyable + winapi_mutex_wrapper(const winapi_mutex_wrapper &); + winapi_mutex_wrapper &operator=(const winapi_mutex_wrapper &); + /// @endcond + + public: + winapi_mutex_wrapper(void *mtx_hnd = winapi::invalid_handle_value) + : winapi_mutex_functions(mtx_hnd) + {} + + ~winapi_mutex_wrapper() + { this->close(); } + + void *release() + { + void *hnd = m_mtx_hnd; + m_mtx_hnd = winapi::invalid_handle_value; + return hnd; + } + + void *handle() const + { return m_mtx_hnd; } + + bool open_or_create(const char *name, const permissions &perm) + { + if(m_mtx_hnd == winapi::invalid_handle_value){ + 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; + } + else{ + return false; + } + } + + void close() + { + if(m_mtx_hnd != winapi::invalid_handle_value){ + winapi::close_handle(m_mtx_hnd); + m_mtx_hnd = winapi::invalid_handle_value; + } + } + + void swap(winapi_mutex_wrapper &other) + { void *tmp = m_mtx_hnd; m_mtx_hnd = other.m_mtx_hnd; other.m_mtx_hnd = tmp; } +}; + +} //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/windows/winapi_semaphore_wrapper.hpp b/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp new file mode 100644 index 0000000000..2dd7845627 --- /dev/null +++ b/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp @@ -0,0 +1,198 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (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_SEMAPHORE_WRAPPER_HPP +#define BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/creation_tags.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/detail/win32_api.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/errors.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <limits> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class winapi_semaphore_functions +{ + /// @cond + + //Non-copyable + winapi_semaphore_functions(const winapi_semaphore_functions &); + winapi_semaphore_functions &operator=(const winapi_semaphore_functions &); + /// @endcond + + public: + winapi_semaphore_functions(void *hnd) + : m_sem_hnd(hnd) + {} + + void post(long count = 1) + { + long prev_count; + winapi::release_semaphore(m_sem_hnd, count, &prev_count); + } + + 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); + } + } + + 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); + } + } + + 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); + } + } + + long value() const + { + long count, limit; + if(!winapi::get_semaphore_info(m_sem_hnd, count, limit)) + return 0; + return count; + } + + long limit() const + { + long count, limit; + if(!winapi::get_semaphore_info(m_sem_hnd, count, limit)) + return 0; + return limit; + } + + /// @cond + protected: + void *m_sem_hnd; + /// @endcond +}; + + +//Swappable semaphore wrapper +class winapi_semaphore_wrapper + : public winapi_semaphore_functions +{ + winapi_semaphore_wrapper(const winapi_semaphore_wrapper &); + winapi_semaphore_wrapper &operator=(const winapi_semaphore_wrapper &); + + public: + + //Long is 32 bits in windows + static const long MaxCount = long(0x7FFFFFFF); + + winapi_semaphore_wrapper(void *hnd = winapi::invalid_handle_value) + : winapi_semaphore_functions(hnd) + {} + + ~winapi_semaphore_wrapper() + { this->close(); } + + void *release() + { + void *hnd = m_sem_hnd; + m_sem_hnd = winapi::invalid_handle_value; + return hnd; + } + + void *handle() const + { return m_sem_hnd; } + + bool open_or_create( const char *name + , long sem_count + , long max_count + , const permissions &perm + , bool &created) + { + if(m_sem_hnd == winapi::invalid_handle_value){ + m_sem_hnd = winapi::open_or_create_semaphore + ( name + , sem_count + , max_count + , (winapi::interprocess_security_attributes*)perm.get_permissions() + ); + created = winapi::get_last_error() != winapi::error_already_exists; + return m_sem_hnd != winapi::invalid_handle_value; + } + else{ + return false; + } + } + + bool open_semaphore(const char *name) + { + if(m_sem_hnd == winapi::invalid_handle_value){ + m_sem_hnd = winapi::open_semaphore(name); + return m_sem_hnd != winapi::invalid_handle_value; + } + else{ + return false; + } + } + + void close() + { + if(m_sem_hnd != winapi::invalid_handle_value){ + winapi::close_handle(m_sem_hnd); + m_sem_hnd = winapi::invalid_handle_value; + } + } + + void swap(winapi_semaphore_wrapper &other) + { void *tmp = m_sem_hnd; m_sem_hnd = other.m_sem_hnd; other.m_sem_hnd = tmp; } +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP diff --git a/boost/interprocess/sync/xsi/xsi_named_mutex.hpp b/boost/interprocess/sync/xsi/xsi_named_mutex.hpp index 3dffdcc2ed..485b1ac101 100644 --- a/boost/interprocess/sync/xsi/xsi_named_mutex.hpp +++ b/boost/interprocess/sync/xsi/xsi_named_mutex.hpp @@ -62,20 +62,20 @@ class xsi_named_mutex xsi_named_mutex(open_or_create_t, const char *path, boost::uint8_t id, int perm = 0666) { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, path, id, perm); } - //!Moves the ownership of "moved"'s named mutex to *this. - //!After the call, "moved" does not represent any named mutex + //!Moves the ownership of "moved"'s named mutex to *this. + //!After the call, "moved" does not represent any named mutex //!Does not throw xsi_named_mutex(BOOST_RV_REF(xsi_named_mutex) moved) { this->swap(moved); } //!Moves the ownership of "moved"'s named mutex to *this. - //!After the call, "moved" does not represent any 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 @@ -126,11 +126,11 @@ class xsi_named_mutex /// @cond -inline xsi_named_mutex::xsi_named_mutex() +inline xsi_named_mutex::xsi_named_mutex() : m_semid(-1), m_key(-1), m_id(0), m_perm(0), m_path() {} -inline xsi_named_mutex::~xsi_named_mutex() +inline xsi_named_mutex::~xsi_named_mutex() { this->priv_close(); } inline const char *xsi_named_mutex::get_path() const @@ -142,7 +142,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 diff --git a/boost/interprocess/windows_shared_memory.hpp b/boost/interprocess/windows_shared_memory.hpp index 9a8b3f47dd..76601bb363 100644 --- a/boost/interprocess/windows_shared_memory.hpp +++ b/boost/interprocess/windows_shared_memory.hpp @@ -72,26 +72,26 @@ class windows_shared_memory windows_shared_memory(open_or_create_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, size, perm); } - //!Tries to open a shared memory object with name "name", with the access mode "mode". + //!Tries to open a shared memory object with name "name", with the access mode "mode". //!If the file does not previously exist, it throws an error. windows_shared_memory(open_only_t, const char *name, mode_t mode) { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, 0, permissions()); } - //!Moves the ownership of "moved"'s shared memory object to *this. - //!After the call, "moved" does not represent any shared memory object. + //!Moves the ownership of "moved"'s shared memory object to *this. + //!After the call, "moved" does not represent any shared memory object. //!Does not throw windows_shared_memory(BOOST_RV_REF(windows_shared_memory) moved) : m_handle(0) { this->swap(moved); } //!Moves the ownership of "moved"'s shared memory to *this. - //!After the call, "moved" does not represent any shared memory. + //!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 @@ -129,21 +129,21 @@ class windows_shared_memory /// @cond -inline windows_shared_memory::windows_shared_memory() +inline windows_shared_memory::windows_shared_memory() : m_handle(0) {} -inline windows_shared_memory::~windows_shared_memory() +inline windows_shared_memory::~windows_shared_memory() { this->priv_close(); } 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 @@ -157,22 +157,26 @@ inline bool windows_shared_memory::priv_open_or_create { m_name = filename ? filename : ""; - unsigned long file_map_access = 0; + unsigned long protection = 0; unsigned long map_access = 0; switch(mode) { + //"protection" is for "create_file_mapping" + //"map_access" is for "open_file_mapping" + //Add section query (strange that read or access does not grant it...) + //to obtain the size of the mapping. copy_on_write is equal to section_query. case read_only: - file_map_access |= winapi::page_readonly; - map_access |= winapi::file_map_read; + protection |= winapi::page_readonly; + map_access |= winapi::file_map_read | winapi::section_query; break; case read_write: - file_map_access |= winapi::page_readwrite; - map_access |= winapi::file_map_write; + protection |= winapi::page_readwrite; + map_access |= winapi::file_map_write | winapi::section_query; break; case copy_on_write: - file_map_access |= winapi::page_writecopy; - map_access |= winapi::file_map_copy; + protection |= winapi::page_writecopy; + map_access |= winapi::file_map_copy; break; default: { @@ -184,16 +188,13 @@ inline bool windows_shared_memory::priv_open_or_create switch(type){ case ipcdetail::DoOpen: - m_handle = winapi::open_file_mapping - (map_access, filename); + m_handle = winapi::open_file_mapping(map_access, filename); break; case ipcdetail::DoCreate: case ipcdetail::DoOpenOrCreate: { - __int64 s = size; - unsigned long high_size(s >> 32), low_size((boost::uint32_t)s); m_handle = winapi::create_file_mapping - ( winapi::invalid_handle_value, file_map_access, high_size, low_size, filename + ( winapi::invalid_handle_value, protection, size, filename , (winapi::interprocess_security_attributes*)perm.get_permissions()); } break; diff --git a/boost/interprocess/xsi_shared_memory.hpp b/boost/interprocess/xsi_shared_memory.hpp index 3d09c77399..e84d9b1c54 100644 --- a/boost/interprocess/xsi_shared_memory.hpp +++ b/boost/interprocess/xsi_shared_memory.hpp @@ -78,21 +78,21 @@ class xsi_shared_memory xsi_shared_memory(open_only_t, const xsi_key &key) { this->priv_open_or_create(ipcdetail::DoOpen, key, permissions(), 0); } - //!Moves the ownership of "moved"'s shared memory object to *this. - //!After the call, "moved" does not represent any shared memory object. + //!Moves the ownership of "moved"'s shared memory object to *this. + //!After the call, "moved" does not represent any shared memory object. //!Does not throw xsi_shared_memory(BOOST_RV_REF(xsi_shared_memory) moved) : m_shmid(-1) { this->swap(moved); } //!Moves the ownership of "moved"'s shared memory to *this. - //!After the call, "moved" does not represent any shared memory. + //!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 @@ -129,11 +129,11 @@ class xsi_shared_memory /// @cond -inline xsi_shared_memory::xsi_shared_memory() +inline xsi_shared_memory::xsi_shared_memory() : m_shmid(-1) {} -inline xsi_shared_memory::~xsi_shared_memory() +inline xsi_shared_memory::~xsi_shared_memory() {} inline int xsi_shared_memory::get_shmid() const |