diff options
Diffstat (limited to 'boost/interprocess')
178 files changed, 7869 insertions, 4576 deletions
diff --git a/boost/interprocess/allocators/adaptive_pool.hpp b/boost/interprocess/allocators/adaptive_pool.hpp index a85202b4ee..d21fe1eda4 100644 --- a/boost/interprocess/allocators/adaptive_pool.hpp +++ b/boost/interprocess/allocators/adaptive_pool.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP #define BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -40,7 +40,7 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail{ @@ -66,7 +66,7 @@ class adaptive_pool_base typedef adaptive_pool_base <Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> self_t; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template <int dummy> struct node_pool @@ -77,7 +77,7 @@ class adaptive_pool_base static type *get(void *p) { return static_cast<type*>(p); } }; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED BOOST_STATIC_ASSERT((Version <=2)); @@ -105,18 +105,18 @@ class adaptive_pool_base //!adaptive_pool_base template<class T2> struct rebind - { + { typedef adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //!Not assignable from related adaptive_pool_base template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char O2> adaptive_pool_base& operator= (const adaptive_pool_base<Version2, T2, SegmentManager2, N2, F2, O2>&); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor from a segment manager. If not present, constructs a node @@ -129,8 +129,8 @@ class adaptive_pool_base //!count of the associated node pool. Never throws adaptive_pool_base(const adaptive_pool_base &other) : mp_node_pool(other.get_node_pool()) - { - node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); + { + node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); } //!Assignment from other adaptive_pool_base @@ -169,10 +169,10 @@ class adaptive_pool_base friend void swap(self_t &alloc1, self_t &alloc2) { ipcdetail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: void_pointer mp_node_pool; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!Equality test for same type @@ -211,7 +211,7 @@ class adaptive_pool_v1 template<class T2> struct rebind - { + { typedef adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -228,7 +228,7 @@ class adaptive_pool_v1 } //namespace ipcdetail{ -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!An STL node allocator that uses a segment manager as memory //!source. The internal pointer type will of the same type (raw, smart) as @@ -251,7 +251,7 @@ template < class T , unsigned char OverheadPercent > class adaptive_pool - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) : public ipcdetail::adaptive_pool_base < 2 , T @@ -260,7 +260,7 @@ class adaptive_pool , MaxFreeBlocks , OverheadPercent > - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED @@ -271,7 +271,7 @@ class adaptive_pool template<class T2> struct rebind - { + { typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -303,7 +303,7 @@ class adaptive_pool //!adaptive_pool template<class T2> struct rebind - { + { typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -400,12 +400,12 @@ class adaptive_pool //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - multiallocation_chain allocate_many(size_type elem_size, size_type num_elements); + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); //!Allocates n_elements elements, each one of size elem_sizes[i]in a //!contiguous block //!of memory. The elements must be deallocated - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements); + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); //!Allocates many elements of size elem_size in a contiguous block //!of memory. The minimum number to be allocated is min_elements, @@ -413,7 +413,7 @@ class adaptive_pool //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - void deallocate_many(multiallocation_chain chain); + void deallocate_many(multiallocation_chain &chain); //!Allocates just one object. Memory allocated with this function //!must be deallocated only with deallocate_one(). @@ -426,7 +426,7 @@ class adaptive_pool //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - multiallocation_chain allocate_individual(size_type num_elements); + void allocate_individual(size_type num_elements, multiallocation_chain &chain); //!Deallocates memory previously allocated with allocate_one(). //!You should never use deallocate_one to deallocate memory allocated @@ -439,7 +439,7 @@ class adaptive_pool //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain it); + void deallocate_individual(multiallocation_chain &chain); #endif }; diff --git a/boost/interprocess/allocators/allocator.hpp b/boost/interprocess/allocators/allocator.hpp index 38e8c6901a..e3b5cc86c8 100644 --- a/boost/interprocess/allocators/allocator.hpp +++ b/boost/interprocess/allocators/allocator.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_ALLOCATOR_HPP #define BOOST_INTERPROCESS_ALLOCATOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -57,7 +57,7 @@ class allocator typedef SegmentManager segment_manager; typedef typename SegmentManager::void_pointer void_pointer; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //Self type @@ -85,7 +85,7 @@ class allocator //Pointer to the allocator alloc_ptr_t mp_mngr; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: typedef T value_type; @@ -104,18 +104,18 @@ class allocator typedef boost::interprocess::version_type<allocator, 2> version; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Experimental. Don't use. typedef boost::container::container_detail::transform_multiallocation_chain <typename SegmentManager::multiallocation_chain, T>multiallocation_chain; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Obtains an allocator that allocates //!objects of type T2 template<class T2> struct rebind - { + { typedef allocator<T2, SegmentManager> other; }; @@ -145,8 +145,9 @@ class allocator pointer allocate(size_type count, cvoid_ptr hint = 0) { (void)hint; - if(count > this->max_size()) + if(size_overflows<sizeof(T)>(count)){ throw bad_alloc(); + } return pointer(static_cast<value_type*>(mp_mngr->allocate(count*sizeof(T)))); } @@ -169,7 +170,7 @@ class allocator //!pointed by p can hold. This size only works for memory allocated with //!allocate, allocation_command and allocate_many. size_type size(const pointer &p) const - { + { return (size_type)mp_mngr->size(ipcdetail::to_raw_pointer(p))/sizeof(T); } @@ -189,19 +190,20 @@ class allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - multiallocation_chain allocate_many - (size_type elem_size, size_type num_elements) + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain) { - return multiallocation_chain(mp_mngr->allocate_many(sizeof(T)*elem_size, num_elements)); + if(size_overflows<sizeof(T)>(elem_size)){ + throw bad_alloc(); + } + mp_mngr->allocate_many(elem_size*sizeof(T), num_elements, chain); } //!Allocates n_elements elements, each one of size elem_sizes[i]in a //!contiguous block //!of memory. The elements must be deallocated - multiallocation_chain allocate_many - (const size_type *elem_sizes, size_type n_elements) + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain) { - multiallocation_chain(mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T))); + mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T), chain); } //!Allocates many elements of size elem_size in a contiguous block @@ -210,10 +212,8 @@ class allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - void deallocate_many(multiallocation_chain chain) - { - return mp_mngr->deallocate_many(chain.extract_multiallocation_chain()); - } + void deallocate_many(multiallocation_chain &chain) + { mp_mngr->deallocate_many(chain); } //!Allocates just one object. Memory allocated with this function //!must be deallocated only with deallocate_one(). @@ -227,9 +227,8 @@ class allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - multiallocation_chain allocate_individual - (size_type num_elements) - { return this->allocate_many(1, num_elements); } + void allocate_individual(size_type num_elements, multiallocation_chain &chain) + { this->allocate_many(1, num_elements, chain); } //!Deallocates memory previously allocated with allocate_one(). //!You should never use deallocate_one to deallocate memory allocated @@ -243,8 +242,8 @@ class allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain chain) - { return this->deallocate_many(boost::move(chain)); } + void deallocate_individual(multiallocation_chain &chain) + { this->deallocate_many(chain); } //!Returns address of mutable object. //!Never throws @@ -286,7 +285,7 @@ bool operator!=(const allocator<T, SegmentManager> &alloc1, } //namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template<class T> struct has_trivial_destructor; @@ -297,7 +296,7 @@ struct has_trivial_destructor { static const bool value = true; }; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace boost { diff --git a/boost/interprocess/allocators/cached_adaptive_pool.hpp b/boost/interprocess/allocators/cached_adaptive_pool.hpp index 98af033fe6..7b1921b254 100644 --- a/boost/interprocess/allocators/cached_adaptive_pool.hpp +++ b/boost/interprocess/allocators/cached_adaptive_pool.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP #define BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -33,7 +33,7 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail { @@ -69,7 +69,7 @@ class cached_adaptive_pool_v1 template<class T2> struct rebind - { + { typedef cached_adaptive_pool_v1 <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -91,7 +91,7 @@ class cached_adaptive_pool_v1 } //namespace ipcdetail{ -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!An STL node allocator that uses a segment manager as memory //!source. The internal pointer type will of the same type (raw, smart) as @@ -117,7 +117,7 @@ template < class T , unsigned char OverheadPercent > class cached_adaptive_pool - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) : public ipcdetail::cached_allocator_impl < T , ipcdetail::shared_adaptive_node_pool @@ -128,7 +128,7 @@ class cached_adaptive_pool , OverheadPercent > , 2> - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED @@ -149,7 +149,7 @@ class cached_adaptive_pool template<class T2> struct rebind - { + { typedef cached_adaptive_pool <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -183,7 +183,7 @@ class cached_adaptive_pool //!cached_adaptive_pool template<class T2> struct rebind - { + { typedef cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -280,12 +280,12 @@ class cached_adaptive_pool //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - multiallocation_chain allocate_many(size_type elem_size, size_type num_elements); + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); //!Allocates n_elements elements, each one of size elem_sizes[i]in a //!contiguous block //!of memory. The elements must be deallocated - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements); + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); //!Allocates many elements of size elem_size in a contiguous block //!of memory. The minimum number to be allocated is min_elements, @@ -293,7 +293,7 @@ class cached_adaptive_pool //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - void deallocate_many(multiallocation_chain chain); + void deallocate_many(multiallocation_chain &chain); //!Allocates just one object. Memory allocated with this function //!must be deallocated only with deallocate_one(). @@ -319,7 +319,7 @@ class cached_adaptive_pool //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain chain); + void deallocate_individual(multiallocation_chain &chain); //!Sets the new max cached nodes value. This can provoke deallocations //!if "newmax" is less than current cached nodes. Never throws void set_max_cached_nodes(size_type newmax); diff --git a/boost/interprocess/allocators/cached_node_allocator.hpp b/boost/interprocess/allocators/cached_node_allocator.hpp index b0ad0e4ebc..5ac6aab2c0 100644 --- a/boost/interprocess/allocators/cached_node_allocator.hpp +++ b/boost/interprocess/allocators/cached_node_allocator.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP #define BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -34,7 +34,7 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail { @@ -64,7 +64,7 @@ class cached_node_allocator_v1 template<class T2> struct rebind - { + { typedef cached_node_allocator_v1 <T2, SegmentManager, NodesPerBlock> other; }; @@ -86,14 +86,14 @@ class cached_node_allocator_v1 } //namespace ipcdetail{ -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED template < class T , class SegmentManager , std::size_t NodesPerBlock > class cached_node_allocator - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) : public ipcdetail::cached_allocator_impl < T , ipcdetail::shared_node_pool @@ -102,7 +102,7 @@ class cached_node_allocator , NodesPerBlock > , 2> - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED @@ -122,7 +122,7 @@ class cached_node_allocator template<class T2> struct rebind - { + { typedef cached_node_allocator<T2, SegmentManager, NodesPerBlock> other; }; @@ -155,7 +155,7 @@ class cached_node_allocator //!cached_node_allocator template<class T2> struct rebind - { + { typedef cached_node_allocator<T2, SegmentManager> other; }; @@ -252,12 +252,12 @@ class cached_node_allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - multiallocation_chain allocate_many(size_type elem_size, size_type num_elements); + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); //!Allocates n_elements elements, each one of size elem_sizes[i]in a //!contiguous block //!of memory. The elements must be deallocated - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements); + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); //!Allocates many elements of size elem_size in a contiguous block //!of memory. The minimum number to be allocated is min_elements, @@ -265,7 +265,7 @@ class cached_node_allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - void deallocate_many(multiallocation_chain chain); + void deallocate_many(multiallocation_chain &chain); //!Allocates just one object. Memory allocated with this function //!must be deallocated only with deallocate_one(). diff --git a/boost/interprocess/allocators/detail/adaptive_node_pool.hpp b/boost/interprocess/allocators/detail/adaptive_node_pool.hpp index abe183146f..dd697902c4 100644 --- a/boost/interprocess/allocators/detail/adaptive_node_pool.hpp +++ b/boost/interprocess/allocators/detail/adaptive_node_pool.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP #define BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -45,10 +45,16 @@ template< class SegmentManager > class private_adaptive_node_pool : public boost::container::container_detail::private_adaptive_node_pool_impl - <typename SegmentManager::segment_manager_base_type> + < typename SegmentManager::segment_manager_base_type + , ::boost::container::adaptive_pool_flag::size_ordered | + ::boost::container::adaptive_pool_flag::address_ordered + > { typedef boost::container::container_detail::private_adaptive_node_pool_impl - <typename SegmentManager::segment_manager_base_type> base_t; + < typename SegmentManager::segment_manager_base_type + , ::boost::container::adaptive_pool_flag::size_ordered | + ::boost::container::adaptive_pool_flag::address_ordered + > base_t; //Non-copyable private_adaptive_node_pool(); private_adaptive_node_pool(const private_adaptive_node_pool &); @@ -74,7 +80,7 @@ class private_adaptive_node_pool }; //!Pooled shared memory allocator using adaptive pool. Includes -//!a reference count but the class does not delete itself, this is +//!a reference count but the class does not delete itself, this is //!responsibility of user classes. Node size (NodeSize) and the number of //!nodes allocated per block (NodesPerBlock) are known at compile time template< class SegmentManager diff --git a/boost/interprocess/allocators/detail/allocator_common.hpp b/boost/interprocess/allocators/detail/allocator_common.hpp index ba14d3f64d..eb8fbfc314 100644 --- a/boost/interprocess/allocators/detail/allocator_common.hpp +++ b/boost/interprocess/allocators/detail/allocator_common.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP #define BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -26,7 +30,7 @@ #include <boost/container/detail/multiallocation_chain.hpp> #include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp> #include <boost/interprocess/detail/segment_manager_helper.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/type_traits.hpp> #include <boost/interprocess/detail/utilities.hpp> #include <algorithm> //std::swap @@ -73,7 +77,7 @@ namespace ipcdetail { template<class NodePool> struct get_or_create_node_pool_func { - + //!This connects or constructs the unique instance of node_pool_t //!Can throw boost::interprocess::bad_alloc void operator()() @@ -90,7 +94,7 @@ struct get_or_create_node_pool_func //!object parameters get_or_create_node_pool_func(typename NodePool::segment_manager *mngr) : mp_segment_manager(mngr){} - + NodePool *mp_node_pool; typename NodePool::segment_manager *mp_segment_manager; }; @@ -118,7 +122,7 @@ struct destroy_if_last_link_func //Last link, let's destroy the segment_manager mp_node_pool->get_segment_manager()->template destroy<NodePool>(boost::interprocess::unique_instance); - } + } //!Constructor. Initializes function //!object parameters @@ -173,7 +177,7 @@ class cache_impl ~cache_impl() { this->deallocate_all_cached_nodes(); - ipcdetail::destroy_node_pool_if_last_link(ipcdetail::to_raw_pointer(mp_node_pool)); + ipcdetail::destroy_node_pool_if_last_link(ipcdetail::to_raw_pointer(mp_node_pool)); } NodePool *get_node_pool() const @@ -189,34 +193,29 @@ class cache_impl { //If don't have any cached node, we have to get a new list of free nodes from the pool if(m_cached_nodes.empty()){ - m_cached_nodes = mp_node_pool->allocate_nodes(m_max_cached_nodes/2); + mp_node_pool->allocate_nodes(m_max_cached_nodes/2, m_cached_nodes); } - void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.front()); - m_cached_nodes.pop_front(); + void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front()); return ret; } - multiallocation_chain cached_allocation(size_type n) + void cached_allocation(size_type n, multiallocation_chain &chain) { - multiallocation_chain chain; size_type count = n, allocated(0); BOOST_TRY{ //If don't have any cached node, we have to get a new list of free nodes from the pool while(!m_cached_nodes.empty() && count--){ - void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.front()); - m_cached_nodes.pop_front(); + void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front()); chain.push_back(ret); ++allocated; } if(allocated != n){ - multiallocation_chain chain2(mp_node_pool->allocate_nodes(n - allocated)); - chain.splice_after(chain.last(), chain2, chain2.before_begin(), chain2.last(), n - allocated); + mp_node_pool->allocate_nodes(n - allocated, chain); } - return boost::move(chain); } BOOST_CATCH(...){ - this->cached_deallocation(boost::move(chain)); + this->cached_deallocation(chain); BOOST_RETHROW } BOOST_CATCH_END @@ -235,7 +234,7 @@ class cache_impl m_cached_nodes.push_front(ptr); } - void cached_deallocation(multiallocation_chain chain) + void cached_deallocation(multiallocation_chain &chain) { m_cached_nodes.splice_after(m_cached_nodes.before_begin(), chain); @@ -262,7 +261,7 @@ class cache_impl void deallocate_all_cached_nodes() { if(m_cached_nodes.empty()) return; - mp_node_pool->deallocate_nodes(boost::move(m_cached_nodes)); + mp_node_pool->deallocate_nodes(m_cached_nodes); } private: @@ -290,7 +289,7 @@ class cache_impl multiallocation_chain chain; chain.splice_after(chain.before_begin(), m_cached_nodes, m_cached_nodes.before_begin(), it, n); //Deallocate all new linked list at once - mp_node_pool->deallocate_nodes(boost::move(chain)); + mp_node_pool->deallocate_nodes(chain); } public: @@ -335,7 +334,7 @@ class array_allocation_impl //!pointed by p can hold. This size only works for memory allocated with //!allocate, allocation_command and allocate_many. size_type size(const pointer &p) const - { + { return (size_type)this->derived()->get_segment_manager()->size(ipcdetail::to_raw_pointer(p))/sizeof(T); } @@ -355,17 +354,20 @@ class array_allocation_impl //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - multiallocation_chain allocate_many(size_type elem_size, size_type num_elements) + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain) { - return this->derived()->get_segment_manager()->allocate_many(sizeof(T)*elem_size, num_elements); + if(size_overflows<sizeof(T)>(elem_size)){ + throw bad_alloc(); + } + this->derived()->get_segment_manager()->allocate_many(elem_size*sizeof(T), num_elements, chain); } //!Allocates n_elements elements, each one of size elem_sizes[i]in a //!contiguous block //!of memory. The elements must be deallocated - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements) + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain) { - return this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T)); + this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T), chain); } //!Allocates many elements of size elem_size in a contiguous block @@ -374,8 +376,8 @@ class array_allocation_impl //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - void deallocate_many(multiallocation_chain chain) - { return this->derived()->get_segment_manager()->deallocate_many(boost::move(chain)); } + void deallocate_many(multiallocation_chain &chain) + { this->derived()->get_segment_manager()->deallocate_many(chain); } //!Returns the number of elements that could be //!allocated. Never throws @@ -457,14 +459,17 @@ class node_pool_allocation_impl (void)hint; typedef typename node_pool<0>::type node_pool_t; node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); - if(count > this->max_size()) + if(size_overflows<sizeof(T)>(count)){ throw bad_alloc(); - else if(Version == 1 && count == 1) + } + else if(Version == 1 && count == 1){ return pointer(static_cast<value_type*> (pool->allocate_node())); - else + } + else{ return pointer(static_cast<value_type*> - (pool->get_segment_manager()->allocate(sizeof(T)*count))); + (pool->get_segment_manager()->allocate(count*sizeof(T)))); + } } //!Deallocate allocated memory. Never throws @@ -495,11 +500,11 @@ class node_pool_allocation_impl //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - multiallocation_chain allocate_individual(size_type num_elements) + void allocate_individual(size_type num_elements, multiallocation_chain &chain) { typedef typename node_pool<0>::type node_pool_t; node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); - return multiallocation_chain(pool->allocate_nodes(num_elements)); + pool->allocate_nodes(num_elements, chain); } //!Deallocates memory previously allocated with allocate_one(). @@ -518,10 +523,10 @@ class node_pool_allocation_impl //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain chain) + void deallocate_individual(multiallocation_chain &chain) { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes - (chain.extract_multiallocation_chain()); + (chain); } //!Deallocates all free blocks of the pool @@ -605,14 +610,15 @@ class cached_allocator_impl { (void)hint; void * ret; - if(count > this->max_size()) + if(size_overflows<sizeof(T)>(count)){ throw bad_alloc(); + } else if(Version == 1 && count == 1){ ret = m_cache.cached_allocation(); } else{ - ret = this->get_segment_manager()->allocate(sizeof(T)*count); - } + ret = this->get_segment_manager()->allocate(count*sizeof(T)); + } return pointer(static_cast<T*>(ret)); } @@ -640,8 +646,8 @@ class cached_allocator_impl //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - multiallocation_chain allocate_individual(size_type num_elements) - { return multiallocation_chain(this->m_cache.cached_allocation(num_elements)); } + void allocate_individual(size_type num_elements, multiallocation_chain &chain) + { this->m_cache.cached_allocation(num_elements, chain); } //!Deallocates memory previously allocated with allocate_one(). //!You should never use deallocate_one to deallocate memory allocated @@ -655,12 +661,8 @@ class cached_allocator_impl //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain chain) - { - typename node_pool_t::multiallocation_chain mem - (chain.extract_multiallocation_chain()); - m_cache.cached_deallocation(boost::move(mem)); - } + void deallocate_individual(multiallocation_chain &chain) + { m_cache.cached_deallocation(chain); } //!Deallocates all free blocks of the pool void deallocate_free_blocks() @@ -678,9 +680,10 @@ class cached_allocator_impl void deallocate_free_chunks() { m_cache.get_node_pool()->deallocate_free_blocks(); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: cache_impl<node_pool_t> m_cache; + #endif //!defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) }; //!Equality test for same type of @@ -699,7 +702,7 @@ bool operator!=(const cached_allocator_impl<T, N, V> &alloc1, //!Pooled shared memory allocator using adaptive pool. Includes -//!a reference count but the class does not delete itself, this is +//!a reference count but the class does not delete itself, this is //!responsibility of user classes. Node size (NodeSize) and the number of //!nodes allocated per block (NodesPerBlock) are known at compile time template<class private_node_allocator_t> @@ -736,7 +739,7 @@ class shared_pool_impl //----------------------- return private_node_allocator_t::allocate_node(); } - + //!Deallocates an array pointed by ptr. Never throws void deallocate_node(void *ptr) { @@ -745,25 +748,15 @@ class shared_pool_impl //----------------------- private_node_allocator_t::deallocate_node(ptr); } -/* - //!Allocates a singly linked list of n nodes ending in null pointer. - //!can throw boost::interprocess::bad_alloc - void allocate_nodes(multiallocation_chain &nodes, size_type n) - { - //----------------------- - boost::interprocess::scoped_lock<mutex_type> guard(m_header); - //----------------------- - return private_node_allocator_t::allocate_nodes(nodes, n); - } -*/ + //!Allocates n nodes. //!Can throw boost::interprocess::bad_alloc - multiallocation_chain allocate_nodes(const size_type n) + void allocate_nodes(const size_type n, multiallocation_chain &chain) { //----------------------- boost::interprocess::scoped_lock<mutex_type> guard(m_header); //----------------------- - return private_node_allocator_t::allocate_nodes(n); + private_node_allocator_t::allocate_nodes(n, chain); } //!Deallocates a linked list of nodes ending in null pointer. Never throws @@ -776,12 +769,12 @@ class shared_pool_impl } //!Deallocates the nodes pointed by the multiallocation iterator. Never throws - void deallocate_nodes(multiallocation_chain chain) + void deallocate_nodes(multiallocation_chain &chain) { //----------------------- boost::interprocess::scoped_lock<mutex_type> guard(m_header); //----------------------- - private_node_allocator_t::deallocate_nodes(boost::move(chain)); + private_node_allocator_t::deallocate_nodes(chain); } //!Deallocates all the free blocks of memory. Never throws diff --git a/boost/interprocess/allocators/detail/node_pool.hpp b/boost/interprocess/allocators/detail/node_pool.hpp index 562b64863b..cee9cdafc8 100644 --- a/boost/interprocess/allocators/detail/node_pool.hpp +++ b/boost/interprocess/allocators/detail/node_pool.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP #define BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -19,8 +19,6 @@ #include <boost/interprocess/detail/workaround.hpp> #include <boost/intrusive/slist.hpp> -#include <boost/math/common_factor_ct.hpp> - #include <boost/interprocess/detail/utilities.hpp> #include <boost/interprocess/allocators/detail/allocator_common.hpp> #include <boost/container/detail/node_pool_impl.hpp> @@ -37,7 +35,7 @@ namespace ipcdetail { //!Pooled shared memory allocator using single segregated storage. Includes -//!a reference count but the class does not delete itself, this is +//!a reference count but the class does not delete itself, this is //!responsibility of user classes. Node size (NodeSize) and the number of //!nodes allocated per block (NodesPerBlock) are known at compile time template< class SegmentManager, std::size_t NodeSize, std::size_t NodesPerBlock > @@ -73,11 +71,11 @@ class private_node_pool //!Pooled shared memory allocator using single segregated storage. Includes -//!a reference count but the class does not delete itself, this is +//!a reference count but the class does not delete itself, this is //!responsibility of user classes. Node size (NodeSize) and the number of //!nodes allocated per block (NodesPerBlock) are known at compile time //!Pooled shared memory allocator using adaptive pool. Includes -//!a reference count but the class does not delete itself, this is +//!a reference count but the class does not delete itself, this is //!responsibility of user classes. Node size (NodeSize) and the number of //!nodes allocated per block (NodesPerBlock) are known at compile time template< class SegmentManager diff --git a/boost/interprocess/allocators/detail/node_tools.hpp b/boost/interprocess/allocators/detail/node_tools.hpp index da7e4668e8..e7115ece4e 100644 --- a/boost/interprocess/allocators/detail/node_tools.hpp +++ b/boost/interprocess/allocators/detail/node_tools.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP #define BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/allocators/node_allocator.hpp b/boost/interprocess/allocators/node_allocator.hpp index 2c1fe566a3..af522f35b2 100644 --- a/boost/interprocess/allocators/node_allocator.hpp +++ b/boost/interprocess/allocators/node_allocator.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP #define BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -39,7 +39,7 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail{ @@ -63,7 +63,7 @@ class node_allocator_base typedef node_allocator_base <Version, T, SegmentManager, NodesPerBlock> self_t; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template <int dummy> struct node_pool @@ -74,7 +74,7 @@ class node_allocator_base static type *get(void *p) { return static_cast<type*>(p); } }; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED BOOST_STATIC_ASSERT((Version <=2)); @@ -102,11 +102,11 @@ class node_allocator_base //!node_allocator_base template<class T2> struct rebind - { + { typedef node_allocator_base<Version, T2, SegmentManager, NodesPerBlock> other; }; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //!Not assignable from related node_allocator_base template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2> @@ -115,7 +115,7 @@ class node_allocator_base //!Not assignable from other node_allocator_base //node_allocator_base& operator=(const node_allocator_base&); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor from a segment manager. If not present, constructs a node @@ -128,8 +128,8 @@ class node_allocator_base //!count of the associated node pool. Never throws node_allocator_base(const node_allocator_base &other) : mp_node_pool(other.get_node_pool()) - { - node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); + { + node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); } //!Copy constructor from related node_allocator_base. If not present, constructs @@ -168,10 +168,10 @@ class node_allocator_base friend void swap(self_t &alloc1, self_t &alloc2) { ipcdetail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: void_pointer mp_node_pool; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!Equality test for same type @@ -206,7 +206,7 @@ class node_allocator_v1 template<class T2> struct rebind - { + { typedef node_allocator_v1<T2, SegmentManager, NodesPerBlock> other; }; @@ -223,7 +223,7 @@ class node_allocator_v1 } //namespace ipcdetail{ -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!An STL node allocator that uses a segment manager as memory //!source. The internal pointer type will of the same type (raw, smart) as @@ -232,20 +232,20 @@ class node_allocator_v1 //!This node allocator shares a segregated storage between all instances //!of node_allocator with equal sizeof(T) placed in the same segment //!group. NodesPerBlock is the number of nodes allocated at once when the allocator -//!needs runs out of nodes +//!runs out of nodes template < class T , class SegmentManager , std::size_t NodesPerBlock > class node_allocator - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) : public ipcdetail::node_allocator_base < 2 , T , SegmentManager , NodesPerBlock > - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED @@ -256,7 +256,7 @@ class node_allocator template<class T2> struct rebind - { + { typedef node_allocator<T2, SegmentManager, NodesPerBlock> other; }; @@ -288,7 +288,7 @@ class node_allocator //!node_allocator template<class T2> struct rebind - { + { typedef node_allocator<T2, SegmentManager, NodesPerBlock> other; }; @@ -385,12 +385,12 @@ class node_allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - multiallocation_chain allocate_many(size_type elem_size, size_type num_elements); + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); //!Allocates n_elements elements, each one of size elem_sizes[i]in a //!contiguous block //!of memory. The elements must be deallocated - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements); + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); //!Allocates many elements of size elem_size in a contiguous block //!of memory. The minimum number to be allocated is min_elements, @@ -398,7 +398,7 @@ class node_allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - void deallocate_many(multiallocation_chain chain); + void deallocate_many(multiallocation_chain &chain); //!Allocates just one object. Memory allocated with this function //!must be deallocated only with deallocate_one(). @@ -411,7 +411,7 @@ class node_allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - multiallocation_chain allocate_individual(size_type num_elements); + void allocate_individual(size_type num_elements, multiallocation_chain &chain); //!Deallocates memory previously allocated with allocate_one(). //!You should never use deallocate_one to deallocate memory allocated @@ -424,7 +424,7 @@ class node_allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain chain); + void deallocate_individual(multiallocation_chain &chain); #endif }; diff --git a/boost/interprocess/allocators/private_adaptive_pool.hpp b/boost/interprocess/allocators/private_adaptive_pool.hpp index febe85c69d..529dc9d138 100644 --- a/boost/interprocess/allocators/private_adaptive_pool.hpp +++ b/boost/interprocess/allocators/private_adaptive_pool.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP #define BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -38,7 +38,7 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail { @@ -63,7 +63,7 @@ class private_adaptive_pool_base typedef SegmentManager segment_manager; typedef typename SegmentManager::void_pointer void_pointer; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef private_adaptive_pool_base < Version, T, SegmentManager, NodesPerBlock @@ -78,7 +78,7 @@ class private_adaptive_pool_base BOOST_STATIC_ASSERT((Version <=2)); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: typedef typename boost::intrusive:: @@ -102,12 +102,12 @@ class private_adaptive_pool_base //!Obtains node_allocator from other node_allocator template<class T2> struct rebind - { + { typedef private_adaptive_pool_base <Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template <int dummy> struct node_pool @@ -132,7 +132,7 @@ class private_adaptive_pool_base //!Not assignable from other private_adaptive_pool_base private_adaptive_pool_base& operator=(const private_adaptive_pool_base&); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor from a segment manager @@ -170,10 +170,10 @@ class private_adaptive_pool_base friend void swap(self_t &alloc1,self_t &alloc2) { alloc1.m_node_pool.swap(alloc2.m_node_pool); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: node_pool_t m_node_pool; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!Equality test for same type of private_adaptive_pool_base @@ -210,7 +210,7 @@ class private_adaptive_pool_v1 template<class T2> struct rebind - { + { typedef private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -227,7 +227,7 @@ class private_adaptive_pool_v1 } //namespace ipcdetail { -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!An STL node allocator that uses a segment manager as memory //!source. The internal pointer type will of the same type (raw, smart) as @@ -249,7 +249,7 @@ template < class T , unsigned char OverheadPercent > class private_adaptive_pool - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) : public ipcdetail::private_adaptive_pool_base < 2 , T @@ -258,7 +258,7 @@ class private_adaptive_pool , MaxFreeBlocks , OverheadPercent > - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED @@ -269,7 +269,7 @@ class private_adaptive_pool template<class T2> struct rebind - { + { typedef private_adaptive_pool <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -302,7 +302,7 @@ class private_adaptive_pool //!private_adaptive_pool template<class T2> struct rebind - { + { typedef private_adaptive_pool <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; }; @@ -400,12 +400,12 @@ class private_adaptive_pool //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - multiallocation_chain allocate_many(size_type elem_size, size_type num_elements); + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); //!Allocates n_elements elements, each one of size elem_sizes[i]in a //!contiguous block //!of memory. The elements must be deallocated - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements); + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); //!Allocates many elements of size elem_size in a contiguous block //!of memory. The minimum number to be allocated is min_elements, @@ -413,7 +413,7 @@ class private_adaptive_pool //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - void deallocate_many(multiallocation_chain chain); + void deallocate_many(multiallocation_chain &chain); //!Allocates just one object. Memory allocated with this function //!must be deallocated only with deallocate_one(). @@ -426,7 +426,7 @@ class private_adaptive_pool //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - multiallocation_chain allocate_individual(size_type num_elements); + void allocate_individual(size_type num_elements, multiallocation_chain &chain); //!Deallocates memory previously allocated with allocate_one(). //!You should never use deallocate_one to deallocate memory allocated @@ -439,7 +439,7 @@ class private_adaptive_pool //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain chain); + void deallocate_individual(multiallocation_chain &chain); #endif }; diff --git a/boost/interprocess/allocators/private_node_allocator.hpp b/boost/interprocess/allocators/private_node_allocator.hpp index 46b7dd6097..8b546c3354 100644 --- a/boost/interprocess/allocators/private_node_allocator.hpp +++ b/boost/interprocess/allocators/private_node_allocator.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP #define BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -38,7 +38,7 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail { @@ -60,7 +60,7 @@ class private_node_allocator_base typedef SegmentManager segment_manager; typedef typename SegmentManager::void_pointer void_pointer; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef private_node_allocator_base < Version, T, SegmentManager, NodesPerBlock> self_t; @@ -72,7 +72,7 @@ class private_node_allocator_base BOOST_STATIC_ASSERT((Version <=2)); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: @@ -97,12 +97,12 @@ class private_node_allocator_base //!Obtains node_allocator from other node_allocator template<class T2> struct rebind - { + { typedef private_node_allocator_base <Version, T2, SegmentManager, NodesPerBlock> other; }; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template <int dummy> struct node_pool { @@ -124,7 +124,7 @@ class private_node_allocator_base //!Not assignable from other private_node_allocator_base private_node_allocator_base& operator=(const private_node_allocator_base&); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor from a segment manager @@ -162,10 +162,10 @@ class private_node_allocator_base friend void swap(self_t &alloc1,self_t &alloc2) { alloc1.m_node_pool.swap(alloc2.m_node_pool); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: node_pool_t m_node_pool; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!Equality test for same type of private_node_allocator_base @@ -198,7 +198,7 @@ class private_node_allocator_v1 template<class T2> struct rebind - { + { typedef private_node_allocator_v1<T2, SegmentManager, NodesPerBlock> other; }; @@ -215,7 +215,7 @@ class private_node_allocator_v1 } //namespace ipcdetail { -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!An STL node allocator that uses a segment manager as memory //!source. The internal pointer type will of the same type (raw, smart) as @@ -228,14 +228,14 @@ template < class T , std::size_t NodesPerBlock > class private_node_allocator - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) : public ipcdetail::private_node_allocator_base < 2 , T , SegmentManager , NodesPerBlock > - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED @@ -246,7 +246,7 @@ class private_node_allocator template<class T2> struct rebind - { + { typedef private_node_allocator <T2, SegmentManager, NodesPerBlock> other; }; @@ -279,7 +279,7 @@ class private_node_allocator //!private_node_allocator template<class T2> struct rebind - { + { typedef private_node_allocator <T2, SegmentManager, NodesPerBlock> other; }; @@ -377,12 +377,12 @@ class private_node_allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - multiallocation_chain allocate_many(size_type elem_size, size_type num_elements); + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); //!Allocates n_elements elements, each one of size elem_sizes[i]in a //!contiguous block //!of memory. The elements must be deallocated - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements); + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); //!Allocates many elements of size elem_size in a contiguous block //!of memory. The minimum number to be allocated is min_elements, @@ -390,7 +390,7 @@ class private_node_allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. The elements must be deallocated //!with deallocate(...) - void deallocate_many(multiallocation_chain chain); + void deallocate_many(multiallocation_chain &chain); //!Allocates just one object. Memory allocated with this function //!must be deallocated only with deallocate_one(). @@ -403,7 +403,7 @@ class private_node_allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - multiallocation_chain allocate_individual(size_type num_elements); + void allocate_individual(size_type num_elements, multiallocation_chain &chain); //!Deallocates memory previously allocated with allocate_one(). //!You should never use deallocate_one to deallocate memory allocated @@ -416,7 +416,7 @@ class private_node_allocator //!preferred_elements. The number of actually allocated elements is //!will be assigned to received_size. Memory allocated with this function //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain chain); + void deallocate_individual(multiallocation_chain &chain); #endif }; diff --git a/boost/interprocess/anonymous_shared_memory.hpp b/boost/interprocess/anonymous_shared_memory.hpp index 624f57f9c3..aed868fb62 100644 --- a/boost/interprocess/anonymous_shared_memory.hpp +++ b/boost/interprocess/anonymous_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP #define BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/creation_tags.hpp> @@ -35,7 +39,7 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail{ @@ -53,7 +57,7 @@ namespace ipcdetail{ }; } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!A function that creates an anonymous shared memory segment of size "size". //!If "address" is passed the function will try to map the segment in that address. @@ -90,13 +94,13 @@ anonymous_shared_memory(std::size_t size, void *address = 0) , 0); if(address == MAP_FAILED){ - if(fd != -1) + if(fd != -1) close(fd); error_info err = system_error_code(); throw interprocess_exception(err); } - if(fd != -1) + if(fd != -1) close(fd); return ipcdetail::raw_mapped_region_creator::create_posix_mapped_region(address, size); diff --git a/boost/interprocess/containers/allocation_type.hpp b/boost/interprocess/containers/allocation_type.hpp index 660b6cbdbc..cae9612fb4 100644 --- a/boost/interprocess/containers/allocation_type.hpp +++ b/boost/interprocess/containers/allocation_type.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP #define BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -21,9 +21,9 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef int allocation_type; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED static const allocation_type allocate_new = boost::container::allocate_new; static const allocation_type expand_fwd = boost::container::expand_fwd; static const allocation_type expand_bwd = boost::container::expand_bwd; diff --git a/boost/interprocess/containers/containers_fwd.hpp b/boost/interprocess/containers/containers_fwd.hpp index 7852bbc853..4175390599 100644 --- a/boost/interprocess/containers/containers_fwd.hpp +++ b/boost/interprocess/containers/containers_fwd.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,9 +11,9 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP #define BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -35,6 +35,6 @@ using boost::container::ordered_unique_range; #include <boost/interprocess/detail/config_end.hpp> -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED #endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP diff --git a/boost/interprocess/containers/deque.hpp b/boost/interprocess/containers/deque.hpp index 30ca43203f..a40db80a19 100644 --- a/boost/interprocess/containers/deque.hpp +++ b/boost/interprocess/containers/deque.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP #define BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/containers/flat_map.hpp b/boost/interprocess/containers/flat_map.hpp index f18a006c79..744d6e972e 100644 --- a/boost/interprocess/containers/flat_map.hpp +++ b/boost/interprocess/containers/flat_map.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP #define BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/containers/flat_set.hpp b/boost/interprocess/containers/flat_set.hpp index 1b2bf9b4d3..51c49925c0 100644 --- a/boost/interprocess/containers/flat_set.hpp +++ b/boost/interprocess/containers/flat_set.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP #define BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/containers/list.hpp b/boost/interprocess/containers/list.hpp index a75b9759b3..0e855efaaf 100644 --- a/boost/interprocess/containers/list.hpp +++ b/boost/interprocess/containers/list.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_LIST_HPP #define BOOST_INTERPROCESS_CONTAINERS_LIST_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/containers/map.hpp b/boost/interprocess/containers/map.hpp index 2e45ec0630..4efed89c10 100644 --- a/boost/interprocess/containers/map.hpp +++ b/boost/interprocess/containers/map.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_MAP_HPP #define BOOST_INTERPROCESS_CONTAINERS_MAP_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/containers/pair.hpp b/boost/interprocess/containers/pair.hpp index 8ba6d047ac..2ca631db4a 100644 --- a/boost/interprocess/containers/pair.hpp +++ b/boost/interprocess/containers/pair.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP #define BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/containers/set.hpp b/boost/interprocess/containers/set.hpp index db06afea6d..09ea6c116d 100644 --- a/boost/interprocess/containers/set.hpp +++ b/boost/interprocess/containers/set.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_SET_HPP #define BOOST_INTERPROCESS_CONTAINERS_SET_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/containers/slist.hpp b/boost/interprocess/containers/slist.hpp index f93379cb7a..c3e1744ea3 100644 --- a/boost/interprocess/containers/slist.hpp +++ b/boost/interprocess/containers/slist.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP #define BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/containers/stable_vector.hpp b/boost/interprocess/containers/stable_vector.hpp index ae09e6b52f..530056dd6e 100644 --- a/boost/interprocess/containers/stable_vector.hpp +++ b/boost/interprocess/containers/stable_vector.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP #define BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/containers/string.hpp b/boost/interprocess/containers/string.hpp index a11bb904b4..805bfe4f14 100644 --- a/boost/interprocess/containers/string.hpp +++ b/boost/interprocess/containers/string.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_STRING_HPP #define BOOST_INTERPROCESS_CONTAINERS_STRING_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/containers/vector.hpp b/boost/interprocess/containers/vector.hpp index 3a6b411512..bfae4f833f 100644 --- a/boost/interprocess/containers/vector.hpp +++ b/boost/interprocess/containers/vector.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP #define BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/containers/version_type.hpp b/boost/interprocess/containers/version_type.hpp index 247f800f4a..92ef49f31d 100644 --- a/boost/interprocess/containers/version_type.hpp +++ b/boost/interprocess/containers/version_type.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP #define BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/creation_tags.hpp b/boost/interprocess/creation_tags.hpp index 374829ac2b..9ff27bffa0 100644 --- a/boost/interprocess/creation_tags.hpp +++ b/boost/interprocess/creation_tags.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_CREATION_TAGS_HPP #define BOOST_INTERPROCESS_CREATION_TAGS_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> diff --git a/boost/interprocess/detail/atomic.hpp b/boost/interprocess/detail/atomic.hpp index aab1533985..96b7729d7e 100644 --- a/boost/interprocess/detail/atomic.hpp +++ b/boost/interprocess/detail/atomic.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011 +// (C) Copyright Ion Gaztanaga 2006-2012 // (C) Copyright Markus Schoepflin 2007 // (C) Copyright Bryce Lelbach 2010 // @@ -15,6 +15,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP #define BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/cstdint.hpp> @@ -49,10 +53,22 @@ inline boost::uint32_t atomic_cas32 } //namespace interprocess{ } //namespace boost{ -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) #include <boost/interprocess/detail/win32_api.hpp> +#if defined( _MSC_VER ) + extern "C" void _ReadWriteBarrier(void); + #pragma intrinsic(_ReadWriteBarrier) + #define BOOST_INTERPROCESS_READ_WRITE_BARRIER _ReadWriteBarrier() +#elif defined(__GNUC__) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 + #define BOOST_INTERPROCESS_READ_WRITE_BARRIER __sync_synchronize() + #else + #define BOOST_INTERPROCESS_READ_WRITE_BARRIER __asm__ __volatile__("" : : : "memory") + #endif +#endif + namespace boost{ namespace interprocess{ namespace ipcdetail{ @@ -71,7 +87,11 @@ inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) //! Atomically read an boost::uint32_t from memory inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } +{ + const boost::uint32_t val = *mem; + BOOST_INTERPROCESS_READ_WRITE_BARRIER; + return val; +} //! Atomically set an boost::uint32_t in memory //! "mem": pointer to the object @@ -93,7 +113,7 @@ inline boost::uint32_t atomic_cas32 } //namespace interprocess{ } //namespace boost{ -#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(_CRAYC) namespace boost { namespace interprocess { @@ -157,13 +177,24 @@ inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) //! Atomically read an boost::uint32_t from memory inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } +{ + const boost::uint32_t val = *mem; + __asm__ __volatile__ ( "" ::: "memory" ); + return val; +} //! Atomically set an boost::uint32_t in memory //! "mem": pointer to the object //! "param": val value that the object will assume inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) -{ *mem = val; } +{ + __asm__ __volatile__ + ( + "xchgl %0, %1" + : "+r" (val), "+m" (*mem) + :: "memory" + ); +} } //namespace ipcdetail{ } //namespace interprocess{ @@ -213,7 +244,7 @@ inline boost::uint32_t atomic_cas32 "bne- 1b\n\t" "2:" : "=&r"(prev) - : "b" (mem), "r"(cmp), "r" (with) + : "b" (mem), "r" (with), "r" (cmp) : "cc", "memory"); return prev; } @@ -232,7 +263,11 @@ inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) //! Atomically read an boost::uint32_t from memory inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } +{ + const boost::uint32_t val = *mem; + __asm__ __volatile__ ( "" ::: "memory" ); + return val; +} //! Atomically set an boost::uint32_t in memory //! "mem": pointer to the object @@ -390,96 +425,96 @@ inline boost::uint32_t atomic_cas32( } //namespace interprocess{ } //namespace boost{ -#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX) - -#include <builtins.h> - -namespace boost { -namespace interprocess { -namespace ipcdetail{ - -//first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting -//all the functions with casts - -//! From XLC documenation : -//! This function can be used with a subsequent stwcxu call to implement a -//! read-modify-write on a specified memory location. The two functions work -//! together to ensure that if the store is successfully performed, no other -//! processor or mechanism can modify the target doubleword between the time -//! lwarxu function is executed and the time the stwcxu functio ncompletes. -//! "mem" : pointer to the object -//! Returns the value at pointed to by mem -inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem) -{ - return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem))); -} - -//! "mem" : pointer to the object -//! "val" : the value to store -//! Returns true if the update of mem is successful and false if it is -//!unsuccessful -inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val) -{ - return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0); -} - -//! "mem": pointer to the object -//! "val": amount to add -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_add32 - (volatile boost::uint32_t *mem, boost::uint32_t val) -{ - boost::uint32_t oldValue; - do - { - oldValue = lwarxu(mem); - }while (!stwcxu(mem, oldValue+val)); - return oldValue; -} - -//! Atomically increment an apr_uint32_t by 1 -//! "mem": pointer to the object -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) -{ return atomic_add32(mem, 1); } - -//! Atomically decrement an boost::uint32_t by 1 -//! "mem": pointer to the atomic value -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) -{ return atomic_add32(mem, (boost::uint32_t)-1); } - -//! Atomically read an boost::uint32_t from memory -inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } - -//! Compare an boost::uint32_t's value with "cmp". -//! If they are the same swap the value with "with" -//! "mem": pointer to the value -//! "with" what to swap it with -//! "cmp": the value to compare it to -//! Returns the old value of *mem -inline boost::uint32_t atomic_cas32 - (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) -{ - boost::uint32_t oldValue; - boost::uint32_t valueToStore; - do - { - oldValue = lwarxu(mem); - } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue)); - - return oldValue; -} - -//! Atomically set an boost::uint32_t in memory -//! "mem": pointer to the object -//! "param": val value that the object will assume -inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) -{ *mem = val; } - -} //namespace ipcdetail -} //namespace interprocess +#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX) + +#include <builtins.h> + +namespace boost { +namespace interprocess { +namespace ipcdetail{ + +//first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting +//all the functions with casts + +//! From XLC documenation : +//! This function can be used with a subsequent stwcxu call to implement a +//! read-modify-write on a specified memory location. The two functions work +//! together to ensure that if the store is successfully performed, no other +//! processor or mechanism can modify the target doubleword between the time +//! lwarxu function is executed and the time the stwcxu functio ncompletes. +//! "mem" : pointer to the object +//! Returns the value at pointed to by mem +inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem) +{ + return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem))); +} + +//! "mem" : pointer to the object +//! "val" : the value to store +//! Returns true if the update of mem is successful and false if it is +//!unsuccessful +inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val) +{ + return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0); +} + +//! "mem": pointer to the object +//! "val": amount to add +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_add32 + (volatile boost::uint32_t *mem, boost::uint32_t val) +{ + boost::uint32_t oldValue; + do + { + oldValue = lwarxu(mem); + }while (!stwcxu(mem, oldValue+val)); + return oldValue; +} + +//! Atomically increment an apr_uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, 1); } + +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, (boost::uint32_t)-1); } + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } + +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with" what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +inline boost::uint32_t atomic_cas32 + (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) +{ + boost::uint32_t oldValue; + boost::uint32_t valueToStore; + do + { + oldValue = lwarxu(mem); + } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue)); + + return oldValue; +} + +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ *mem = val; } + +} //namespace ipcdetail +} //namespace interprocess } //namespace boost #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) @@ -510,7 +545,7 @@ inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) //! Atomically read an boost::uint32_t from memory inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } +{ boost::uint32_t old_val = *mem; __sync_synchronize(); return old_val; } //! Compare an boost::uint32_t's value with "cmp". //! If they are the same swap the value with "with" @@ -526,7 +561,7 @@ inline boost::uint32_t atomic_cas32 //! "mem": pointer to the object //! "param": val value that the object will assume inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) -{ *mem = val; } +{ __sync_synchronize(); *mem = val; } } //namespace ipcdetail{ } //namespace interprocess{ @@ -552,9 +587,9 @@ inline bool atomic_add_unless32 return c != unless_this; } -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/detail/cast_tags.hpp b/boost/interprocess/detail/cast_tags.hpp index bd91d1b6bb..0019af7933 100644 --- a/boost/interprocess/detail/cast_tags.hpp +++ b/boost/interprocess/detail/cast_tags.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP #define BOOST_INTERPROCESS_CAST_TAGS_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> diff --git a/boost/interprocess/detail/config_begin.hpp b/boost/interprocess/detail/config_begin.hpp index a72f6df1fe..8bcdcac587 100644 --- a/boost/interprocess/detail/config_begin.hpp +++ b/boost/interprocess/detail/config_begin.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -13,10 +13,6 @@ #endif #ifdef BOOST_MSVC - #ifndef _CRT_SECURE_NO_DEPRECATE - #define BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE - #define _CRT_SECURE_NO_DEPRECATE - #endif #pragma warning (push) #pragma warning (disable : 4702) // unreachable code #pragma warning (disable : 4706) // assignment within conditional expression diff --git a/boost/interprocess/detail/config_end.hpp b/boost/interprocess/detail/config_end.hpp index 422458e855..28ec407312 100644 --- a/boost/interprocess/detail/config_end.hpp +++ b/boost/interprocess/detail/config_end.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -9,9 +9,5 @@ ////////////////////////////////////////////////////////////////////////////// #if defined BOOST_MSVC #pragma warning (pop) - #ifdef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE - #undef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE - #undef _CRT_SECURE_NO_DEPRECATE - #endif #endif diff --git a/boost/interprocess/detail/config_external_begin.hpp b/boost/interprocess/detail/config_external_begin.hpp new file mode 100644 index 0000000000..fb578ef013 --- /dev/null +++ b/boost/interprocess/detail/config_external_begin.hpp @@ -0,0 +1,18 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_EXTERNAL_CONFIG_INCLUDED +#define BOOST_INTERPROCESS_EXTERNAL_CONFIG_INCLUDED +#include <boost/config.hpp> +#endif + +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wshadow" +#endif diff --git a/boost/interprocess/detail/config_external_end.hpp b/boost/interprocess/detail/config_external_end.hpp new file mode 100644 index 0000000000..214558f58c --- /dev/null +++ b/boost/interprocess/detail/config_external_end.hpp @@ -0,0 +1,12 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406) +# pragma GCC diagnostic pop +#endif diff --git a/boost/interprocess/detail/file_locking_helpers.hpp b/boost/interprocess/detail/file_locking_helpers.hpp index 2b96e2b6d5..6a7ce8ef3b 100644 --- a/boost/interprocess/detail/file_locking_helpers.hpp +++ b/boost/interprocess/detail/file_locking_helpers.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP #define BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -26,7 +26,7 @@ #include <cstddef> #include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #if defined(BOOST_INTERPROCESS_WINDOWS) @@ -287,7 +287,7 @@ inline bool compare_file_serial(int fd, const locking_file_serial_id &id) id.st_ino == info.st_ino; } -#endif +#endif } //namespace ipcdetail{ } //namespace interprocess{ diff --git a/boost/interprocess/detail/file_wrapper.hpp b/boost/interprocess/detail/file_wrapper.hpp index 586e20db4d..507ec478dc 100644 --- a/boost/interprocess/detail/file_wrapper.hpp +++ b/boost/interprocess/detail/file_wrapper.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,11 +11,15 @@ #ifndef BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP #define BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> #include <boost/interprocess/creation_tags.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/creation_tags.hpp> namespace boost { @@ -24,9 +28,9 @@ namespace ipcdetail{ class file_wrapper { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) BOOST_MOVABLE_BUT_NOT_COPYABLE(file_wrapper) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Default constructor. @@ -60,10 +64,10 @@ class file_wrapper //!After the call, "moved" does not represent any file. //!Does not throw file_wrapper &operator=(BOOST_RV_REF(file_wrapper) moved) - { + { file_wrapper tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps to file_wrappers. @@ -73,7 +77,7 @@ class file_wrapper //!Erases a file from the system. //!Returns false on error. Never throws static bool remove(const char *name); - + //!Sets the size of the file void truncate(offset_t length); @@ -122,10 +126,10 @@ inline bool file_wrapper::get_size(offset_t &size) const { return get_file_size((file_handle_t)m_handle, size); } inline void file_wrapper::swap(file_wrapper &other) -{ +{ std::swap(m_handle, other.m_handle); std::swap(m_mode, other.m_mode); - m_filename.swap(other.m_filename); + m_filename.swap(other.m_filename); } inline mapping_handle_t file_wrapper::get_mapping_handle() const @@ -167,7 +171,8 @@ inline bool file_wrapper::priv_open_or_create //Check for error if(m_handle == invalid_file()){ - throw interprocess_exception(error_info(system_error_code())); + error_info err = system_error_code(); + throw interprocess_exception(err); } m_mode = mode; diff --git a/boost/interprocess/detail/in_place_interface.hpp b/boost/interprocess/detail/in_place_interface.hpp index b43b2ce165..5af5a0d2df 100644 --- a/boost/interprocess/detail/in_place_interface.hpp +++ b/boost/interprocess/detail/in_place_interface.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP #define BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -47,7 +47,7 @@ template<class T> struct placement_destroy : public in_place_interface { placement_destroy() - : in_place_interface(::boost::alignment_of<T>::value, sizeof(T), typeid(T).name()) + : in_place_interface(::boost::alignment_of<T>::value, sizeof(T), typeid(T).name()) {} virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) diff --git a/boost/interprocess/detail/intermodule_singleton.hpp b/boost/interprocess/detail/intermodule_singleton.hpp index 054322699d..a99934893d 100644 --- a/boost/interprocess/detail/intermodule_singleton.hpp +++ b/boost/interprocess/detail/intermodule_singleton.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_HPP #define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -20,8 +20,9 @@ #ifdef BOOST_INTERPROCESS_WINDOWS #include <boost/interprocess/detail/windows_intermodule_singleton.hpp> +#else + #include <boost/interprocess/detail/portable_intermodule_singleton.hpp> #endif -#include <boost/interprocess/detail/portable_intermodule_singleton.hpp> namespace boost{ namespace interprocess{ @@ -30,7 +31,7 @@ namespace ipcdetail{ //Now this class is a singleton, initializing the singleton in //the first get() function call if LazyInit is false. If true //then the singleton will be initialized when loading the module. -template<typename C, bool LazyInit = true, bool Phoenix = true> +template<typename C, bool LazyInit = true, bool Phoenix = false> class intermodule_singleton #ifdef BOOST_INTERPROCESS_WINDOWS : public windows_intermodule_singleton<C, LazyInit, Phoenix> diff --git a/boost/interprocess/detail/intermodule_singleton_common.hpp b/boost/interprocess/detail/intermodule_singleton_common.hpp index 0710c0bbc1..10c9eceabb 100644 --- a/boost/interprocess/detail/intermodule_singleton_common.hpp +++ b/boost/interprocess/detail/intermodule_singleton_common.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP #define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -20,8 +20,10 @@ #include <boost/interprocess/detail/atomic.hpp> #include <boost/interprocess/detail/os_thread_functions.hpp> +#include <boost/interprocess/exceptions.hpp> #include <boost/type_traits/type_with_alignment.hpp> #include <boost/interprocess/detail/mpl.hpp> +#include <boost/interprocess/sync/spin/wait.hpp> #include <boost/assert.hpp> #include <cstddef> #include <cstdio> @@ -121,7 +123,8 @@ class intermodule_singleton_common //Now try to create the singleton in global map. //This function solves concurrency issues //between threads of several modules - void *tmp = constructor(get_map()); + ThreadSafeGlobalMap *const pmap = get_map_ptr(); + void *tmp = constructor(*pmap); //Increment the module reference count that reflects how many //singletons this module holds, so that we can safely destroy //module global map object when no singleton is left @@ -144,6 +147,7 @@ class intermodule_singleton_common //If previous state was initializing, this means that another winner thread is //trying to initialize the singleton. Just wait until completes its work. else if(previous_module_singleton_initialized == Initializing){ + spin_wait swait; while(1){ previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized); if(previous_module_singleton_initialized >= Initialized){ @@ -151,7 +155,7 @@ class intermodule_singleton_common break; } else if(previous_module_singleton_initialized == Initializing){ - thread_yield(); + swait.yield(); } else{ //This can't be happening! @@ -178,7 +182,8 @@ class intermodule_singleton_common //Note: this destructor might provoke a Phoenix singleton //resurrection. This means that this_module_singleton_count //might change after this call. - destructor(ptr, get_map()); + ThreadSafeGlobalMap * const pmap = get_map_ptr(); + destructor(ptr, *pmap); ptr = 0; //Memory barrier to make sure pointer is nulled. @@ -197,14 +202,15 @@ class intermodule_singleton_common } private: - static ThreadSafeGlobalMap &get_map() + static ThreadSafeGlobalMap *get_map_ptr() { - return *static_cast<ThreadSafeGlobalMap *>(static_cast<void *>(&mem_holder.map_mem)); + return static_cast<ThreadSafeGlobalMap *>(static_cast<void*>(mem_holder.map_mem)); } static void initialize_global_map_handle() { //Obtain unique map name and size + spin_wait swait; while(1){ //Try to pass map state to initializing ::boost::uint32_t tmp = atomic_cas32(&this_module_map_initialized, Initializing, Uninitialized); @@ -217,7 +223,7 @@ class intermodule_singleton_common } //If some other thread is doing the work wait else if(tmp == Initializing){ - thread_yield(); + swait.yield(); } else{ //(tmp == Uninitialized) //If not initialized try it again? @@ -225,16 +231,17 @@ class intermodule_singleton_common //Remove old global map from the system intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem(); //in-place construction of the global map class + ThreadSafeGlobalMap * const pmap = get_map_ptr(); intermodule_singleton_helpers::thread_safe_global_map_dependant - <ThreadSafeGlobalMap>::construct_map(static_cast<void*>(&get_map())); + <ThreadSafeGlobalMap>::construct_map(static_cast<void*>(pmap)); //Use global map's internal lock to initialize the lock file //that will mark this gmem as "in use". typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>:: - lock_file_logic f(get_map()); + lock_file_logic f(*pmap); //If function failed (maybe a competing process has erased the shared //memory between creation and file locking), retry with a new instance. if(f.retry()){ - get_map().~ThreadSafeGlobalMap(); + pmap->~ThreadSafeGlobalMap(); atomic_write32(&this_module_map_initialized, Destroyed); } else{ @@ -257,9 +264,10 @@ class intermodule_singleton_common //This module is being unloaded, so destroy //the global map object of this module //and unlink the global map if it's the last + ThreadSafeGlobalMap * const pmap = get_map_ptr(); typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>:: - unlink_map_logic f(get_map()); - (get_map()).~ThreadSafeGlobalMap(); + unlink_map_logic f(*pmap); + pmap->~ThreadSafeGlobalMap(); atomic_write32(&this_module_map_initialized, Destroyed); //Do some cleanup for other processes old gmem instances intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem(); @@ -274,11 +282,11 @@ class intermodule_singleton_common //Values: Uninitialized, Initializing, Initialized, Broken static volatile boost::uint32_t this_module_map_initialized; - //Raw memory to construct the global map manager - static struct mem_holder_t + //Raw memory to construct the global map manager + static union mem_holder_t { + unsigned char map_mem [sizeof(ThreadSafeGlobalMap)]; ::boost::detail::max_align aligner; - char map_mem [sizeof(ThreadSafeGlobalMap)]; } mem_holder; }; @@ -308,7 +316,7 @@ struct ref_count_ptr //Now this class is a singleton, initializing the singleton in -//the first get() function call if LazyInit is false. If true +//the first get() function call if LazyInit is true. If false //then the singleton will be initialized when loading the module. template<typename C, bool LazyInit, bool Phoenix, class ThreadSafeGlobalMap> class intermodule_singleton_impl @@ -356,9 +364,9 @@ class intermodule_singleton_impl ~lifetime_type_lazy() { - if(!Phoenix){ - atexit_work(); - } + //if(!Phoenix){ + //atexit_work(); + //} } //Dummy volatile so that the compiler can't resolve its value at compile-time @@ -384,7 +392,7 @@ class intermodule_singleton_impl struct init_atomic_func { init_atomic_func(ThreadSafeGlobalMap &m) - : m_map(m) + : m_map(m), ret_ptr() {} void operator()() @@ -405,13 +413,13 @@ class intermodule_singleton_impl throw; } } - if(Phoenix){ + //if(Phoenix){ std::atexit(&atexit_work); - } + //} atomic_inc32(&rcount->singleton_ref_count); ret_ptr = rcount->ptr; } - void *data() const + void *data() const { return ret_ptr; } private: @@ -446,12 +454,9 @@ class intermodule_singleton_impl delete pc; } } - void *data() const - { return ret_ptr; } - + private: ThreadSafeGlobalMap &m_map; - void *ret_ptr; }; //A wrapper to execute init_atomic_func diff --git a/boost/interprocess/detail/interprocess_tester.hpp b/boost/interprocess/detail/interprocess_tester.hpp index 2581776745..8c00c4c0c4 100644 --- a/boost/interprocess/detail/interprocess_tester.hpp +++ b/boost/interprocess/detail/interprocess_tester.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP #define BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP +#if defined(_MSC_VER) +# pragma once +#endif + namespace boost{ namespace interprocess{ namespace ipcdetail{ diff --git a/boost/interprocess/detail/intersegment_ptr.hpp b/boost/interprocess/detail/intersegment_ptr.hpp index 16d3505883..fa1b277ef4 100644 --- a/boost/interprocess/detail/intersegment_ptr.hpp +++ b/boost/interprocess/detail/intersegment_ptr.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP #define BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -177,7 +177,7 @@ struct intersegment_base void set_mode(std::size_t mode) { - BOOST_ASSERT(mode < is_max_mode); + BOOST_ASSERT(mode < is_max_mode); members.direct.ctrl = mode; } @@ -309,13 +309,13 @@ struct flat_map_intersegment void *ptr_base; void *this_base; get_segment_info_and_offset(this, this_info, this_offset, this_base); - + if(!this_info.group){ this->set_mode(is_in_stack); this->members.direct.addr = const_cast<void*>(ptr); } else{ - get_segment_info_and_offset(ptr, ptr_info, ptr_offset, ptr_base); + get_segment_info_and_offset(ptr, ptr_info, ptr_offset, ptr_base); if(ptr_info.group != this_info.group){ this->set_mode(is_pointee_outside); @@ -383,7 +383,7 @@ struct flat_map_intersegment }; vector<segment_data> m_segments; multi_segment_services &m_ms_services; - + public: segment_group_t(multi_segment_services &ms_services) : m_ms_services(ms_services) @@ -445,7 +445,7 @@ struct flat_map_intersegment typedef Mutex mutex_type; //!Maps base addresses and segment information //!(size and segment group and id)* - + ptr_to_segment_info_t m_ptr_to_segment_info; ~mappings_t() @@ -486,7 +486,7 @@ struct flat_map_intersegment --it; char * segment_base = const_cast<char*>(reinterpret_cast<const char*>(it->first)); std::size_t segment_size = it->second.size; - + if(segment_base <= reinterpret_cast<const char*>(ptr) && (segment_base + segment_size) >= reinterpret_cast<const char*>(ptr)){ segment = it->second; @@ -552,7 +552,7 @@ struct flat_map_intersegment s_groups.insert(segment_group_t(*services)); BOOST_ASSERT(ret.second); return &*ret.first; - } + } } static bool delete_group(segment_group_id id) @@ -574,7 +574,7 @@ struct flat_map_intersegment } } return success; - } + } } }; @@ -663,17 +663,17 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex> //!Pointer-like -> operator. It can return 0 pointer. //!Never throws. - pointer operator->() const + pointer operator->() const { return self_t::get(); } //!Dereferencing operator, if it is a null intersegment_ptr behavior //!is undefined. Never throws. - reference operator* () const + reference operator* () const { return *(self_t::get()); } //!Indexing operator. //!Never throws. - reference operator[](std::ptrdiff_t idx) const + reference operator[](std::ptrdiff_t idx) const { return self_t::get()[idx]; } //!Assignment from pointer (saves extra conversion). @@ -690,15 +690,15 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex> //!are assignable, intersegment_ptrs will be assignable. Never throws. template <class T2> intersegment_ptr& operator= (const intersegment_ptr<T2> & ptr) - { + { pointer p(ptr.get()); (void)p; - base_t::set_from_other(ptr); return *this; + base_t::set_from_other(ptr); return *this; } //!intersegment_ptr + std::ptrdiff_t. //!Never throws. - intersegment_ptr operator+ (std::ptrdiff_t idx) const - { + intersegment_ptr operator+ (std::ptrdiff_t idx) const + { intersegment_ptr result (*this); result.inc_offset(idx*sizeof(T)); return result; @@ -706,8 +706,8 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex> //!intersegment_ptr - std::ptrdiff_t. //!Never throws. - intersegment_ptr operator- (std::ptrdiff_t idx) const - { + intersegment_ptr operator- (std::ptrdiff_t idx) const + { intersegment_ptr result (*this); result.dec_offset(idx*sizeof(T)); return result; @@ -745,7 +745,7 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex> //!Safe bool conversion operator. //!Never throws. - operator unspecified_bool_type() const + operator unspecified_bool_type() const { return base_t::is_null()? 0 : &self_t::unspecified_bool_type_func; } //!Not operator. Not needed in theory, but improves portability. @@ -784,12 +784,12 @@ class intersegment_ptr : public flat_map_intersegment<interprocess_mutex> template <class T1, class T2> inline bool operator ==(const intersegment_ptr<T1> &left, const intersegment_ptr<T2> &right) -{ +{ //Make sure both pointers can be compared bool e = typename intersegment_ptr<T1>::pointer(0) == typename intersegment_ptr<T2>::pointer(0); (void)e; - return left._equal(right); + return left._equal(right); } //!Returns true if *this is less than other. @@ -798,12 +798,12 @@ bool operator ==(const intersegment_ptr<T1> &left, template <class T1, class T2> inline bool operator <(const intersegment_ptr<T1> &left, const intersegment_ptr<T2> &right) -{ +{ //Make sure both pointers can be compared bool e = typename intersegment_ptr<T1>::pointer(0) < typename intersegment_ptr<T2>::pointer(0); (void)e; - return left._less(right); + return left._less(right); } template<class T1, class T2> inline diff --git a/boost/interprocess/detail/managed_global_memory.hpp b/boost/interprocess/detail/managed_global_memory.hpp index 39dd0b1e6d..baa6361e69 100644 --- a/boost/interprocess/detail/managed_global_memory.hpp +++ b/boost/interprocess/detail/managed_global_memory.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP #define BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -23,7 +23,7 @@ #include <boost/interprocess/sync/spin/recursive_mutex.hpp> #include <boost/interprocess/detail/managed_memory_impl.hpp> #include <boost/interprocess/detail/managed_open_or_create_impl.hpp> -#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> +#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> #include <boost/interprocess/indexes/iset_index.hpp> #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/permissions.hpp> @@ -47,7 +47,7 @@ struct intermodule_types struct open_or_create { typedef managed_open_or_create_impl - <Device, mem_algo::Alignment, FileBased> type; + <Device, mem_algo::Alignment, FileBased, false> type; }; }; @@ -62,7 +62,7 @@ class basic_managed_global_memory > , private intermodule_types::open_or_create<Device, FileBased>::type { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef typename intermodule_types::template open_or_create<Device, FileBased>::type base2_t; typedef basic_managed_memory_impl @@ -83,7 +83,7 @@ class basic_managed_global_memory private: typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_global_memory) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //functions diff --git a/boost/interprocess/detail/managed_memory_impl.hpp b/boost/interprocess/detail/managed_memory_impl.hpp index f9ecb8a860..b77c53274d 100644 --- a/boost/interprocess/detail/managed_memory_impl.hpp +++ b/boost/interprocess/detail/managed_memory_impl.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP #define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -90,7 +90,7 @@ class basic_managed_memory_impl typedef typename segment_manager:: const_unique_iterator const_unique_iterator; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef typename segment_manager::char_ptr_holder_t char_ptr_holder_t; @@ -98,7 +98,7 @@ class basic_managed_memory_impl typedef typename segment_manager::multiallocation_chain multiallocation_chain; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation; @@ -172,14 +172,14 @@ class basic_managed_memory_impl //This function should not throw. The index construction can //throw if constructor allocates memory. So we must catch it. BOOST_TRY{ - //Let's construct the allocator in memory + //Let's construct the allocator in memory mp_header = new(addr) segment_manager(size); } BOOST_CATCH(...){ return false; } BOOST_CATCH_END - return true; + return true; } //!Connects to a segment manager in the reserved buffer. Never throws. @@ -192,7 +192,7 @@ class basic_managed_memory_impl //!Frees resources. Never throws. bool close_impl() - { + { bool ret = mp_header != 0; mp_header = 0; return ret; @@ -254,12 +254,12 @@ class basic_managed_memory_impl handle_t get_handle_from_address (const void *ptr) const { return (handle_t)(reinterpret_cast<const char*>(ptr) - - reinterpret_cast<const char*>(this->get_address())); + reinterpret_cast<const char*>(this->get_address())); } //!Returns true if the address belongs to the managed memory segment bool belongs_to_segment (const void *ptr) const - { + { return ptr >= this->get_address() && ptr < (reinterpret_cast<const char*>(this->get_address()) + this->get_size()); } @@ -292,7 +292,7 @@ class basic_managed_memory_impl allocation_command (boost::interprocess::allocation_type command, size_type limit_size, size_type preferred_size,size_type &received_size, T *reuse_ptr = 0) - { + { return mp_header->allocation_command (command, limit_size, preferred_size, received_size, reuse_ptr); } @@ -303,31 +303,37 @@ class basic_managed_memory_impl void * allocate_aligned(size_type nbytes, size_type alignment) { return mp_header->allocate_aligned(nbytes, alignment); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Experimental. Don't use. - //!Allocates n_elements of elem_size bytes. - multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements) - { return mp_header->allocate_many(elem_bytes, num_elements); } + //!Allocates n_elements of elem_bytes bytes. + //!Throws bad_alloc on failure. chain.size() is not increased on failure. + void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) + { mp_header->allocate_many(elem_bytes, n_elements, chain); } - //!Allocates n_elements, each one of elem_sizes[i] bytes. - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements) - { return mp_header->allocate_many(elem_sizes, n_elements); } + //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes. + //!Throws bad_alloc on failure. chain.size() is not increased on failure. + void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) + { mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); } - //!Allocates n_elements of elem_size bytes. - multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements, std::nothrow_t nothrow) - { return mp_header->allocate_many(elem_bytes, num_elements, nothrow); } + //!Allocates n_elements of elem_bytes bytes. + //!Non-throwing version. chain.size() is not increased on failure. + void allocate_many(std::nothrow_t, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) + { mp_header->allocate_many(std::nothrow_t(), elem_bytes, n_elements, chain); } - //!Allocates n_elements, each one of elem_sizes[i] bytes. - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements, std::nothrow_t nothrow) - { return mp_header->allocate_many(elem_sizes, n_elements, nothrow); } + //!Allocates n_elements, each one of + //!element_lengths[i]*sizeof_element bytes. + //!Non-throwing version. chain.size() is not increased on failure. + void allocate_many(std::nothrow_t, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) + { mp_header->allocate_many(std::nothrow_t(), elem_sizes, n_elements, sizeof_element, chain); } - //!Allocates n_elements, each one of elem_sizes[i] bytes. - void deallocate_many(multiallocation_chain chain) - { return mp_header->deallocate_many(boost::move(chain)); } + //!Deallocates all elements contained in chain. + //!Never throws. + void deallocate_many(multiallocation_chain &chain) + { mp_header->deallocate_many(chain); } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Marks previously allocated memory as free. Never throws. void deallocate (void *addr) @@ -603,7 +609,7 @@ class basic_managed_memory_impl { mp_header->template destroy_ptr<T>(ptr); } //!Returns the name of an object created with construct/find_or_construct - //!functions. Does not throw + //!functions. If ptr points to an unique instance typeid(T).name() is returned. template<class T> static const char_type *get_instance_name(const T *ptr) { return segment_manager::get_instance_name(ptr); } @@ -697,14 +703,14 @@ class basic_managed_memory_impl get_deleter() { return mp_header->template get_deleter<T>(); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Tries to find a previous named allocation address. Returns a memory //!buffer and the object count. If not found returned pointer is 0. //!Never throws. template <class T> std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name) { return mp_header->template find_no_lock<T>(name); } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED protected: //!Swaps the segment manager's managed by this managed memory segment. @@ -719,20 +725,40 @@ class basic_managed_memory_impl template<class BasicManagedMemoryImpl> class create_open_func { + typedef typename BasicManagedMemoryImpl::size_type size_type; + public: + create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type) : m_frontend(frontend), m_type(type){} - bool operator()(void *addr, typename BasicManagedMemoryImpl::size_type size, bool created) const - { - if(((m_type == DoOpen) && created) || - ((m_type == DoCreate) && !created)) + bool operator()(void *addr, std::size_t size, bool created) const + { + if( ((m_type == DoOpen) && created) || + ((m_type == DoCreate) && !created) || + //Check for overflow + size_type(-1) < size ){ return false; + } + else if(created){ + return m_frontend->create_impl(addr, static_cast<size_type>(size)); + } + else{ + return m_frontend->open_impl (addr, static_cast<size_type>(size)); + } + } - if(created) - return m_frontend->create_impl(addr, size); - else - return m_frontend->open_impl (addr, size); + std::size_t get_min_size() const + { + const size_type sz = m_frontend->get_segment_manager()->get_min_size(); + if(sz > std::size_t(-1)){ + //The minimum size is not representable by std::size_t + BOOST_ASSERT(false); + return std::size_t(-1); + } + else{ + return static_cast<std::size_t>(sz); + } } private: diff --git a/boost/interprocess/detail/managed_multi_shared_memory.hpp b/boost/interprocess/detail/managed_multi_shared_memory.hpp index 654c8bb9f3..4c2ef14dcc 100644 --- a/boost/interprocess/detail/managed_multi_shared_memory.hpp +++ b/boost/interprocess/detail/managed_multi_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP #define BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -36,7 +36,7 @@ #include <boost/assert.hpp> //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> +#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> #include <boost/interprocess/sync/mutex_family.hpp> //!\file @@ -69,10 +69,10 @@ class basic_managed_multi_shared_memory <CharType, MemoryAlgorithm, IndexType> self_t; typedef ipcdetail::basic_managed_memory_impl <CharType, MemoryAlgorithm, IndexType> base_t; - + typedef typename MemoryAlgorithm::void_pointer void_pointer; typedef typename ipcdetail:: - managed_open_or_create_impl<shared_memory_object, MemoryAlgorithm::Alignment> managed_impl; + managed_open_or_create_impl<shared_memory_object, MemoryAlgorithm::Alignment, true, false> managed_impl; typedef typename void_pointer::segment_group_id segment_group_id; typedef typename base_t::size_type size_type; @@ -100,7 +100,7 @@ class basic_managed_multi_shared_memory // if(!m_shmem.create(m_mem_name, size, m_addr)) // return 0; // return m_shmem.get_address(); -// } +// } // private: // shared_memory &m_shmem; // const char *m_mem_name; @@ -134,7 +134,7 @@ class basic_managed_multi_shared_memory typename shmem_list_t::value_type &m_impl = *mp_frontend->m_shmem_list.rbegin(); return result_type(m_impl.get_real_address(), m_impl.get_real_size()-1); }*/ - return result_type(static_cast<void *>(0), 0); + return result_type(static_cast<void *>(0), 0); } virtual bool update_segments () @@ -174,7 +174,7 @@ class basic_managed_multi_shared_memory : mp_frontend(frontend), m_type(type), m_segment_number(segment_number){} bool operator()(void *addr, size_type size, bool created) const - { + { if(((m_type == DoOpen) && created) || ((m_type == DoCreate) && !created)) return false; @@ -211,9 +211,23 @@ class basic_managed_multi_shared_memory } return false; } + + std::size_t get_min_size() const + { + const size_type sz = mp_frontend->get_segment_manager()->get_min_size(); + if(sz > std::size_t(-1)){ + //The minimum size is not representable by std::size_t + BOOST_ASSERT(false); + return std::size_t(-1); + } + else{ + return static_cast<std::size_t>(sz); + } + } + self_t * const mp_frontend; type_t m_type; - size_type m_segment_number; + size_type m_segment_number; }; //!Functor to execute atomically when closing a shared memory segment. @@ -226,7 +240,7 @@ class basic_managed_multi_shared_memory : mp_frontend(frontend){} void operator()(const mapped_region ®ion, bool last) const - { + { if(last) mp_frontend->destroy_impl(); else mp_frontend->close_impl(); } @@ -251,7 +265,7 @@ class basic_managed_multi_shared_memory const permissions &perm = permissions()) : m_group_services(get_this_pointer()) { - priv_open_or_create(create_open_func::DoCreate,name, size, perm); + priv_open_or_create(create_open_func::DoCreate,name, size, perm); } basic_managed_multi_shared_memory(open_or_create_t, @@ -301,7 +315,7 @@ class basic_managed_multi_shared_memory if(group){ void_pointer::delete_group(group); } - return false; + return false; } bool priv_new_segment(typename create_open_func::type_t type, @@ -368,7 +382,7 @@ class basic_managed_multi_shared_memory //!Frees resources. Never throws. void priv_close() - { + { if(!m_shmem_list.empty()){ bool ret; //Obtain group identifier @@ -385,7 +399,7 @@ class basic_managed_multi_shared_memory m_shmem_list.clear(); } } - + private: shmem_list_t m_shmem_list; group_services m_group_services; diff --git a/boost/interprocess/detail/managed_open_or_create_impl.hpp b/boost/interprocess/detail/managed_open_or_create_impl.hpp index a4f1f15817..bd08be56d3 100644 --- a/boost/interprocess/detail/managed_open_or_create_impl.hpp +++ b/boost/interprocess/detail/managed_open_or_create_impl.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL #define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/os_thread_functions.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> @@ -25,13 +29,14 @@ #include <boost/interprocess/permissions.hpp> #include <boost/type_traits/alignment_of.hpp> #include <boost/type_traits/type_with_alignment.hpp> +#include <boost/interprocess/sync/spin/wait.hpp> #include <boost/move/move.hpp> #include <boost/cstdint.hpp> namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail{ class interprocess_tester; } @@ -48,13 +53,13 @@ class xsi_key; template<> struct managed_open_or_create_impl_device_id_t<xsi_shared_memory_file_wrapper> -{ +{ typedef xsi_key type; }; #endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS - -/// @endcond + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED namespace ipcdetail { @@ -79,12 +84,12 @@ class managed_open_or_create_impl_device_holder<true, DeviceAbstraction> const DeviceAbstraction &get_device() const { return dev; } - + private: DeviceAbstraction dev; }; -template<class DeviceAbstraction, std::size_t MemAlignment = 0, bool FileBased = true, bool StoreDevice = true> +template<class DeviceAbstraction, std::size_t MemAlignment, bool FileBased, bool StoreDevice> class managed_open_or_create_impl : public managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction> { @@ -94,9 +99,9 @@ class managed_open_or_create_impl typedef typename managed_open_or_create_impl_device_id_t<DeviceAbstraction>::type device_id_t; typedef managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction> DevHolder; enum - { - UninitializedSegment, - InitializingSegment, + { + UninitializedSegment, + InitializingSegment, InitializedSegment, CorruptedSegment }; @@ -222,10 +227,10 @@ class managed_open_or_create_impl { this->swap(moved); } managed_open_or_create_impl &operator=(BOOST_RV_REF(managed_open_or_create_impl) moved) - { + { managed_open_or_create_impl tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } ~managed_open_or_create_impl() @@ -309,14 +314,18 @@ class managed_open_or_create_impl { typedef bool_<FileBased> file_like_t; (void)mode; - error_info err; bool created = false; bool ronly = false; bool cow = false; DeviceAbstraction dev; - if(type != DoOpen && size < ManagedOpenOrCreateUserOffset){ - throw interprocess_exception(error_info(size_error)); + if(type != DoOpen){ + //Check if the requested size is enough to build the managed metadata + const std::size_t func_min_size = construct_func.get_min_size(); + if( (std::size_t(-1) - ManagedOpenOrCreateUserOffset) < func_min_size || + size < (func_min_size + ManagedOpenOrCreateUserOffset) ){ + throw interprocess_exception(error_info(size_error)); + } } //Check size can be represented by offset_t (used by truncate) if(type != DoOpen && !check_offset_t_size<FileBased>(size, file_like_t())){ @@ -349,6 +358,7 @@ class managed_open_or_create_impl //file and know if we have really created it or just open it //drop me a e-mail! bool completed = false; + spin_wait swait; while(!completed){ try{ create_device<FileBased>(dev, id, size, perm, file_like_t()); @@ -366,8 +376,8 @@ class managed_open_or_create_impl created = false; completed = true; } - catch(interprocess_exception &ex){ - if(ex.get_error_code() != not_found_error){ + catch(interprocess_exception &e){ + if(e.get_error_code() != not_found_error){ throw; } } @@ -379,7 +389,7 @@ class managed_open_or_create_impl catch(...){ throw; } - thread_yield(); + swait.yield(); } } @@ -426,11 +436,13 @@ class managed_open_or_create_impl else{ if(FileBased){ offset_t filesize = 0; + spin_wait swait; while(filesize == 0){ if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){ - throw interprocess_exception(error_info(system_error_code())); + error_info err = system_error_code(); + throw interprocess_exception(err); } - thread_yield(); + swait.yield(); } if(filesize == 1){ throw interprocess_exception(error_info(corrupted_error)); @@ -442,8 +454,9 @@ class managed_open_or_create_impl boost::uint32_t *patomic_word = static_cast<boost::uint32_t*>(region.get_address()); boost::uint32_t value = atomic_read32(patomic_word); + spin_wait swait; while(value == InitializingSegment || value == UninitializedSegment){ - thread_yield(); + swait.yield(); value = atomic_read32(patomic_word); } @@ -461,6 +474,11 @@ class managed_open_or_create_impl } } + friend void swap(managed_open_or_create_impl &left, managed_open_or_create_impl &right) + { + left.swap(right); + } + private: friend class interprocess_tester; void dont_close_on_destruction() @@ -469,11 +487,6 @@ class managed_open_or_create_impl mapped_region m_mapped_region; }; -template<class DeviceAbstraction> -inline void swap(managed_open_or_create_impl<DeviceAbstraction> &x - ,managed_open_or_create_impl<DeviceAbstraction> &y) -{ x.swap(y); } - } //namespace ipcdetail { } //namespace interprocess { diff --git a/boost/interprocess/detail/math_functions.hpp b/boost/interprocess/detail/math_functions.hpp index 2fc457c683..3826f161e2 100644 --- a/boost/interprocess/detail/math_functions.hpp +++ b/boost/interprocess/detail/math_functions.hpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Stephen Cleary 2000. -// (C) Copyright Ion Gaztanaga 2007-2011. +// (C) Copyright Ion Gaztanaga 2007-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -16,6 +16,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP #define BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <climits> #include <boost/static_assert.hpp> @@ -93,7 +97,7 @@ inline std::size_t floor_log2 (std::size_t x) std::size_t n = x; std::size_t log2 = 0; - + for(std::size_t shift = Bits >> 1; shift; shift >>= 1){ std::size_t tmp = n >> shift; if (tmp) diff --git a/boost/interprocess/detail/min_max.hpp b/boost/interprocess/detail/min_max.hpp index 1f4ebdfc33..a5d01f404b 100644 --- a/boost/interprocess/detail/min_max.hpp +++ b/boost/interprocess/detail/min_max.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -13,7 +13,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP #define BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/detail/move.hpp b/boost/interprocess/detail/move.hpp index 1ec43b211b..22df7bd771 100644 --- a/boost/interprocess/detail/move.hpp +++ b/boost/interprocess/detail/move.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2011. +// (C) Copyright Ion Gaztanaga 2010-2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -14,7 +14,11 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP #define BOOST_INTERPROCESS_DETAIL_MOVE_HPP -#include <boost/move/move.hpp> +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/move/utility_core.hpp> namespace boost { namespace interprocess { diff --git a/boost/interprocess/detail/mpl.hpp b/boost/interprocess/detail/mpl.hpp index e2c7f52d24..29f3893038 100644 --- a/boost/interprocess/detail/mpl.hpp +++ b/boost/interprocess/detail/mpl.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -13,7 +13,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP #define BOOST_INTERPROCESS_DETAIL_MPL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/detail/multi_segment_services.hpp b/boost/interprocess/detail/multi_segment_services.hpp index d1451d3379..dd9d5f82fd 100644 --- a/boost/interprocess/detail/multi_segment_services.hpp +++ b/boost/interprocess/detail/multi_segment_services.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP #define BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/detail/named_proxy.hpp b/boost/interprocess/detail/named_proxy.hpp index c2aafed9ac..ee6668c2d5 100644 --- a/boost/interprocess/detail/named_proxy.hpp +++ b/boost/interprocess/detail/named_proxy.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP #define BOOST_INTERPROCESS_NAMED_PROXY_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -26,7 +26,7 @@ #ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING #include <boost/interprocess/detail/preprocessor.hpp> #else -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/variadic_templates_tools.hpp> #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING @@ -93,7 +93,7 @@ struct CtorNArg : public placement_destroy<T> {} tuple<Args&...> args_; -}; +}; //!Describes a proxy class that implements named //!allocation syntax. @@ -119,7 +119,7 @@ class named_proxy template<class ...Args> T *operator()(Args &&...args) const - { + { CtorNArg<T, is_iterator, Args...> &&ctor_obj = CtorNArg<T, is_iterator, Args...> (boost::forward<Args>(args)...); return mp_mngr->template @@ -199,7 +199,7 @@ struct Ctor0Arg : public placement_destroy<T> // private: // void construct(void *mem, true_) // { new((void*)mem)T(*m_p1, *m_p2); } -// +// // void construct(void *mem, false_) // { new((void*)mem)T(m_p1, m_p2); } // @@ -293,7 +293,7 @@ class named_proxy //!makes a named allocation and calls the //!default constructor T *operator()() const - { + { Ctor0Arg<T> ctor_obj; return mp_mngr->template generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj); diff --git a/boost/interprocess/detail/os_file_functions.hpp b/boost/interprocess/detail/os_file_functions.hpp index 08decd9bc4..1b54807ab1 100644 --- a/boost/interprocess/detail/os_file_functions.hpp +++ b/boost/interprocess/detail/os_file_functions.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP #define BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/errors.hpp> @@ -19,8 +23,9 @@ #include <string> #include <limits> #include <climits> +#include <boost/type_traits/make_unsigned.hpp> -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) # include <boost/interprocess/detail/win32_api.hpp> #else # ifdef BOOST_HAS_UNISTD_H @@ -45,7 +50,7 @@ namespace boost { namespace interprocess { -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) typedef void * file_handle_t; typedef long long offset_t; @@ -66,6 +71,9 @@ typedef enum { file_begin = winapi::file_begin , file_current = winapi::file_current } file_pos_t; +typedef unsigned long map_options_t; +static const map_options_t default_map_options = map_options_t(-1); + namespace ipcdetail{ inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd) @@ -90,34 +98,47 @@ inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd) inline bool create_directory(const char *path) { return winapi::create_directory(path); } -inline const char *get_temporary_path() -{ return std::getenv("TMP"); } - +inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len) +{ + required_len = 0; + //std::size_t is always bigger or equal than unsigned long in Windows systems + //In case std::size_t is bigger than unsigned long + unsigned long buf = buf_len; + if(buf_len != buf){ //maybe overflowed + return false; + } + required_len = winapi::get_temp_path(buf_len, buffer); + const bool ret = !(buf_len < required_len); + if(ret && buffer[required_len-1] == '\\'){ + buffer[required_len-1] = 0; + } + return ret; +} inline file_handle_t create_new_file (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) -{ +{ unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; return winapi::create_file ( name, (unsigned int)mode, winapi::create_new, attr - , (winapi::interprocess_security_attributes*)perm.get_permissions()); + , (winapi::interprocess_security_attributes*)perm.get_permissions()); } inline file_handle_t create_or_open_file (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) -{ +{ unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; return winapi::create_file ( name, (unsigned int)mode, winapi::open_always, attr - , (winapi::interprocess_security_attributes*)perm.get_permissions()); + , (winapi::interprocess_security_attributes*)perm.get_permissions()); } inline file_handle_t open_existing_file (const char *name, mode_t mode, bool temporary = false) -{ +{ unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; return winapi::create_file - (name, (unsigned int)mode, winapi::open_existing, attr, 0); + (name, (unsigned int)mode, winapi::open_existing, attr, 0); } inline bool delete_file(const char *name) @@ -129,10 +150,10 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size) if(!winapi::get_file_size(hnd, filesize)) return false; - const offset_t max_filesize = (std::numeric_limits<offset_t>::max)(); + typedef boost::make_unsigned<offset_t>::type uoffset_t; + const uoffset_t max_filesize = uoffset_t((std::numeric_limits<offset_t>::max)()); //Avoid unused variable warnings in 32 bit systems - (void)max_filesize; - if( sizeof(std::size_t) >= sizeof(offset_t) && size > std::size_t(max_filesize) ){ + if(uoffset_t(size) > max_filesize){ winapi::set_last_error(winapi::error_file_too_large); return false; } @@ -177,7 +198,7 @@ inline bool get_file_pointer(file_handle_t hnd, offset_t &off) { return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); } inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata) -{ +{ unsigned long written; return 0 != winapi::write_file(hnd, data, (unsigned long)numdata, &written, 0); } @@ -189,9 +210,9 @@ inline bool close_file(file_handle_t hnd) { return 0 != winapi::close_handle(hnd); } inline bool acquire_file_lock(file_handle_t hnd) -{ +{ static winapi::interprocess_overlapped overlapped; - const unsigned long len = ~((unsigned long)(0u)); + const unsigned long len = ((unsigned long)-1); // winapi::interprocess_overlapped overlapped; // std::memset(&overlapped, 0, sizeof(overlapped)); return winapi::lock_file_ex @@ -199,8 +220,8 @@ inline bool acquire_file_lock(file_handle_t hnd) } inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired) -{ - const unsigned long len = ~((unsigned long)(0u)); +{ + const unsigned long len = ((unsigned long)-1); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); if(!winapi::lock_file_ex @@ -208,30 +229,30 @@ inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired) 0, len, len, &overlapped)){ return winapi::get_last_error() == winapi::error_lock_violation ? acquired = false, true : false; - + } return (acquired = true); } inline bool release_file_lock(file_handle_t hnd) -{ - const unsigned long len = ~((unsigned long)(0u)); +{ + const unsigned long len = ((unsigned long)-1); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped); } inline bool acquire_file_lock_sharable(file_handle_t hnd) -{ - const unsigned long len = ~((unsigned long)(0u)); +{ + const unsigned long len = ((unsigned long)-1); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped); } inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) -{ - const unsigned long len = ~((unsigned long)(0u)); +{ + const unsigned long len = ((unsigned long)-1); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); if(!winapi::lock_file_ex @@ -253,7 +274,7 @@ inline bool delete_subdirectories_recursive void * hFile; // Handle to directory std::string strFilePath; // Filepath std::string strPattern; // Pattern - winapi::win32_find_data_t FileInformation; // File information + winapi::win32_find_data FileInformation; // File information //Find all files and directories strPattern = refcstrRootDirectory + "\\*.*"; @@ -269,8 +290,10 @@ inline bool delete_subdirectories_recursive //If it's a directory, go recursive if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){ // Delete subdirectory - if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1)) + if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1)){ + winapi::find_close(hFile); return false; + } } //If it's a file, just delete it else{ @@ -278,7 +301,7 @@ inline bool delete_subdirectories_recursive //if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0) //return winapi::get_last_error(); // Delete file - winapi::delete_file(strFilePath.c_str()); + winapi::unlink_file(strFilePath.c_str()); } } //Go to the next file @@ -319,7 +342,7 @@ template<class Function> inline bool for_each_file_in_dir(const char *dir, Function f) { void * hFile; // Handle to directory - winapi::win32_find_data_t FileInformation; // File information + winapi::win32_find_data FileInformation; // File information //Get base directory std::string str(dir); @@ -352,7 +375,7 @@ inline bool for_each_file_in_dir(const char *dir, Function f) } -#else //#if (defined BOOST_INTERPROCESS_WINDOWS) +#else //#if defined (BOOST_INTERPROCESS_WINDOWS) typedef int file_handle_t; typedef off_t offset_t; @@ -375,6 +398,9 @@ typedef enum { file_begin = SEEK_SET , file_current = SEEK_CUR } file_pos_t; +typedef int map_options_t; +static const map_options_t default_map_options = map_options_t(-1); + namespace ipcdetail{ inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd) @@ -391,22 +417,20 @@ inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd) inline bool create_directory(const char *path) { return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; } -inline const char *get_temporary_path() +inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len) { - const char *names[] = {"/tmp", "TMPDIR", "TMP", "TEMP" }; - const int names_size = sizeof(names)/sizeof(names[0]); - struct stat data; - for(int i = 0; i != names_size; ++i){ - if(::stat(names[i], &data) == 0){ - return names[i]; - } + required_len = 5u; + if(buf_len < required_len) + return false; + else{ + std::strcpy(buffer, "/tmp"); } - return "/tmp"; + return true; } inline file_handle_t create_new_file (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) -{ +{ (void)temporary; int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions()); if(ret >= 0){ @@ -433,13 +457,16 @@ inline file_handle_t create_or_open_file break; } } + else{ + break; + } } return ret; } inline file_handle_t open_existing_file (const char *name, mode_t mode, bool temporary = false) -{ +{ (void)temporary; return ::open(name, (int)mode); } @@ -449,17 +476,16 @@ inline bool delete_file(const char *name) inline bool truncate_file (file_handle_t hnd, std::size_t size) { - if(sizeof(off_t) == sizeof(std::size_t)){ - if(size > ((~std::size_t(0)) >> 1)){ - errno = EINVAL; - return false; - } + typedef boost::make_unsigned<off_t>::type uoff_t; + if(uoff_t((std::numeric_limits<off_t>::max)()) < size){ + errno = EINVAL; + return false; } return 0 == ::ftruncate(hnd, off_t(size)); } inline bool get_file_size(file_handle_t hnd, offset_t &size) -{ +{ struct stat data; bool ret = 0 == ::fstat(hnd, &data); if(ret){ @@ -472,7 +498,7 @@ inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos) { return ((off_t)(-1)) != ::lseek(hnd, off, (int)pos); } inline bool get_file_pointer(file_handle_t hnd, offset_t &off) -{ +{ off = ::lseek(hnd, 0, SEEK_CUR); return off != ((off_t)-1); } @@ -522,7 +548,7 @@ inline bool release_file_lock(file_handle_t hnd) } inline bool acquire_file_lock_sharable(file_handle_t hnd) -{ +{ struct ::flock lock; lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; @@ -532,7 +558,7 @@ inline bool acquire_file_lock_sharable(file_handle_t hnd) } inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) -{ +{ struct flock lock; lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; @@ -601,7 +627,7 @@ inline bool delete_subdirectories_recursive || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){ continue; } - if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){ + if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){ continue; } fn = refcstrRootDirectory; @@ -672,7 +698,7 @@ inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this ); } -#endif //#if (defined BOOST_INTERPROCESS_WINDOWS) +#endif //#if defined (BOOST_INTERPROCESS_WINDOWS) inline bool open_or_create_directory(const char *dir_name) { @@ -686,6 +712,18 @@ inline bool open_or_create_directory(const char *dir_name) return true; } +inline std::string get_temporary_path() +{ + std::size_t required_len = 0; + get_temporary_path(0, 0, required_len); + std::string ret_str(required_len, char(0)); + get_temporary_path(&ret_str[0], ret_str.size(), required_len); + while(!ret_str.empty() && !ret_str[ret_str.size()-1]){ + ret_str.erase(ret_str.size()-1); + } + + return ret_str; +} } //namespace ipcdetail{ } //namespace interprocess { diff --git a/boost/interprocess/detail/os_thread_functions.hpp b/boost/interprocess/detail/os_thread_functions.hpp index 8d769fc4e9..4604683645 100644 --- a/boost/interprocess/detail/os_thread_functions.hpp +++ b/boost/interprocess/detail/os_thread_functions.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -8,24 +8,60 @@ // ////////////////////////////////////////////////////////////////////////////// +//Thread launching functions are adapted from boost/detail/lightweight_thread.hpp +// +// boost/detail/lightweight_thread.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP #define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/streams/bufferstream.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <cstddef> +#include <memory> -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined(BOOST_INTERPROCESS_WINDOWS) # include <boost/interprocess/detail/win32_api.hpp> +# include <process.h> #else -# ifdef BOOST_HAS_UNISTD_H -# include <pthread.h> -# include <unistd.h> -# include <sched.h> -# include <time.h> +# include <pthread.h> +# include <unistd.h> +# include <sched.h> +# include <time.h> +# ifdef BOOST_INTERPROCESS_BSD_DERIVATIVE + //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas + //others (FreeBSD & Darwin) need sys/types.h +# include <sys/types.h> +# include <sys/param.h> +# include <sys/sysctl.h> +# endif +//According to the article "C/C++ tip: How to measure elapsed real time for benchmarking" +# if defined(CLOCK_MONOTONIC_PRECISE) //BSD +# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE +# elif defined(CLOCK_MONOTONIC_RAW) //Linux +# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW +# elif defined(CLOCK_HIGHRES) //Solaris +# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES +# elif defined(CLOCK_MONOTONIC) //POSIX (AIX, BSD, Linux, Solaris) +# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC +# elif !defined(CLOCK_MONOTONIC) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) +# include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t +# define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME # else -# error Unknown platform +# error "No high resolution steady clock in your system, please provide a patch" # endif #endif @@ -33,10 +69,11 @@ namespace boost { namespace interprocess { namespace ipcdetail{ -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) typedef unsigned long OS_process_id_t; typedef unsigned long OS_thread_id_t; +typedef void* OS_thread_t; typedef OS_thread_id_t OS_systemwide_thread_id_t; //process @@ -56,11 +93,83 @@ inline OS_thread_id_t get_invalid_thread_id() inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2) { return id1 == id2; } +//return the system tick in ns +inline unsigned long get_system_tick_ns() +{ + unsigned long curres; + winapi::set_timer_resolution(10000, 0, &curres); + //Windows API returns the value in hundreds of ns + return (curres - 1ul)*100ul; +} + +//return the system tick in us +inline unsigned long get_system_tick_us() +{ + unsigned long curres; + winapi::set_timer_resolution(10000, 0, &curres); + //Windows API returns the value in hundreds of ns + return (curres - 1ul)/10ul + 1ul; +} + +typedef unsigned __int64 OS_highres_count_t; + +inline unsigned long get_system_tick_in_highres_counts() +{ + __int64 freq; + unsigned long curres; + winapi::set_timer_resolution(10000, 0, &curres); + //Frequency in counts per second + if(!winapi::query_performance_frequency(&freq)){ + //Tick resolution in ms + return (curres-1ul)/10000ul + 1ul; + } + else{ + //In femtoseconds + __int64 count_fs = (1000000000000000LL - 1LL)/freq + 1LL; + __int64 tick_counts = (static_cast<__int64>(curres)*100000000LL - 1LL)/count_fs + 1LL; + return static_cast<unsigned long>(tick_counts); + } +} + +inline OS_highres_count_t get_current_system_highres_count() +{ + __int64 count; + if(!winapi::query_performance_counter(&count)){ + count = winapi::get_tick_count(); + } + return count; +} + +inline void zero_highres_count(OS_highres_count_t &count) +{ count = 0; } + +inline bool is_highres_count_zero(const OS_highres_count_t &count) +{ return count == 0; } + +template <class Ostream> +inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count) +{ + ostream << count; + return ostream; +} + +inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ return l - r; } + +inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ return l < r; } + +inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r) +{ return l < static_cast<OS_highres_count_t>(r); } + +inline void thread_sleep_tick() +{ winapi::sleep_tick(); } + inline void thread_yield() { winapi::sched_yield(); } inline void thread_sleep(unsigned int ms) -{ winapi::Sleep(ms); } +{ winapi::sleep(ms); } //systemwide thread inline OS_systemwide_thread_id_t get_current_systemwide_thread_id() @@ -88,7 +197,7 @@ inline long double get_current_process_creation_time() { winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime; - get_process_times + winapi::get_process_times ( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime); typedef long double ldouble_t; @@ -97,14 +206,22 @@ inline long double get_current_process_creation_time() CreationTime.dwLowDateTime*resolution; } +inline unsigned int get_num_cores() +{ + winapi::system_info sysinfo; + winapi::get_system_info( &sysinfo ); + //in Windows dw is long which is equal in bits to int + return static_cast<unsigned>(sysinfo.dwNumberOfProcessors); +} -#else //#if (defined BOOST_INTERPROCESS_WINDOWS) +#else //#if defined (BOOST_INTERPROCESS_WINDOWS) +typedef pthread_t OS_thread_t; typedef pthread_t OS_thread_id_t; typedef pid_t OS_process_id_t; struct OS_systemwide_thread_id_t -{ +{ OS_systemwide_thread_id_t() : pid(), tid() {} @@ -164,9 +281,135 @@ inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2) inline void thread_yield() { ::sched_yield(); } +#ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME +typedef struct timespec OS_highres_count_t; +#else +typedef unsigned long long OS_highres_count_t; +#endif + +inline unsigned long get_system_tick_ns() +{ + #ifdef _SC_CLK_TCK + long ticks_per_second =::sysconf(_SC_CLK_TCK); // ticks per sec + if(ticks_per_second <= 0){ //Try a typical value on error + ticks_per_second = 100; + } + return 999999999ul/static_cast<unsigned long>(ticks_per_second)+1ul; + #else + #error "Can't obtain system tick value for your system, please provide a patch" + #endif +} + +inline unsigned long get_system_tick_in_highres_counts() +{ + #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME + return get_system_tick_ns(); + #else + mach_timebase_info_data_t info; + mach_timebase_info(&info); + //ns + return static_cast<unsigned long> + ( + static_cast<double>(get_system_tick_ns()) + / (static_cast<double>(info.numer) / info.denom) + ); + #endif +} + +//return system ticks in us +inline unsigned long get_system_tick_us() +{ + return (get_system_tick_ns()-1)/1000ul + 1ul; +} + +inline OS_highres_count_t get_current_system_highres_count() +{ + #if defined(BOOST_INTERPROCESS_CLOCK_MONOTONIC) + struct timespec count; + ::clock_gettime(BOOST_INTERPROCESS_CLOCK_MONOTONIC, &count); + return count; + #elif defined(BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME) + return ::mach_absolute_time(); + #endif +} + +#ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME + +inline void zero_highres_count(OS_highres_count_t &count) +{ count.tv_sec = 0; count.tv_nsec = 0; } + +inline bool is_highres_count_zero(const OS_highres_count_t &count) +{ return count.tv_sec == 0 && count.tv_nsec == 0; } + +template <class Ostream> +inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count) +{ + ostream << count.tv_sec << "s:" << count.tv_nsec << "ns"; + return ostream; +} + +inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ + OS_highres_count_t res; + + if (l.tv_nsec < r.tv_nsec){ + res.tv_nsec = 1000000000 + l.tv_nsec - r.tv_nsec; + res.tv_sec = l.tv_sec - 1 - r.tv_sec; + } + else{ + res.tv_nsec = l.tv_nsec - r.tv_nsec; + res.tv_sec = l.tv_sec - r.tv_sec; + } + + return res; +} + +inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ return l.tv_sec < r.tv_sec || (l.tv_sec == r.tv_sec && l.tv_nsec < r.tv_nsec); } + +inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r) +{ return !l.tv_sec && (static_cast<unsigned long>(l.tv_nsec) < r); } + +#else + +inline void zero_highres_count(OS_highres_count_t &count) +{ count = 0; } + +inline bool is_highres_count_zero(const OS_highres_count_t &count) +{ return count == 0; } + +template <class Ostream> +inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count) +{ + ostream << count ; + return ostream; +} + +inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ return l - r; } + +inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ return l < r; } + +inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r) +{ return l < static_cast<OS_highres_count_t>(r); } + +#endif + +inline void thread_sleep_tick() +{ + struct timespec rqt; + //Sleep for the half of the tick time + rqt.tv_sec = 0; + rqt.tv_nsec = get_system_tick_ns()/2; + ::nanosleep(&rqt, 0); +} + inline void thread_sleep(unsigned int ms) { - const struct timespec rqt = { ms/1000u, (ms%1000u)*1000000u }; + struct timespec rqt; + rqt.tv_sec = ms/1000u; + rqt.tv_nsec = (ms%1000u)*1000000u; ::nanosleep(&rqt, 0); } @@ -189,7 +432,46 @@ inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id() inline long double get_current_process_creation_time() { return 0.0L; } -#endif //#if (defined BOOST_INTERPROCESS_WINDOWS) +inline unsigned int get_num_cores() +{ + #ifdef _SC_NPROCESSORS_ONLN + long cores = ::sysconf(_SC_NPROCESSORS_ONLN); + // sysconf returns -1 if the name is invalid, the option does not exist or + // does not have a definite limit. + // if sysconf returns some other negative number, we have no idea + // what is going on. Default to something safe. + if(cores <= 0){ + return 1; + } + //Check for overflow (unlikely) + else if(static_cast<unsigned long>(cores) >= + static_cast<unsigned long>(static_cast<unsigned int>(-1))){ + return static_cast<unsigned int>(-1); + } + else{ + return static_cast<unsigned int>(cores); + } + #elif defined(BOOST_INTERPROCESS_BSD_DERIVATIVE) && defined(HW_NCPU) + int request[2] = { CTL_HW, HW_NCPU }; + int num_cores; + std::size_t result_len = sizeof(num_cores); + if ( (::sysctl (request, 2, &num_cores, &result_len, 0, 0) < 0) || (num_cores <= 0) ){ + //Return a safe value + return 1; + } + else{ + return static_cast<unsigned int>(num_cores); + } + #endif +} + +inline int thread_create(OS_thread_t * thread, void *(*start_routine)(void*), void* arg) +{ return pthread_create(thread, 0, start_routine, arg); } + +inline void thread_join(OS_thread_t thread) +{ (void)pthread_join(thread, 0); } + +#endif //#if defined (BOOST_INTERPROCESS_WINDOWS) typedef char pid_str_t[sizeof(OS_process_id_t)*3+1]; @@ -202,6 +484,111 @@ inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid) inline void get_pid_str(pid_str_t &pid_str) { get_pid_str(pid_str, get_current_process_id()); } +#if defined(BOOST_INTERPROCESS_WINDOWS) + +inline int thread_create( OS_thread_t * thread, unsigned (__stdcall * start_routine) (void*), void* arg ) +{ + void* h = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 ); + + if( h != 0 ){ + *thread = h; + return 0; + } + else{ + return 1; + } +} + +inline void thread_join( OS_thread_t thread) +{ + winapi::wait_for_single_object( thread, winapi::infinite_time ); + winapi::close_handle( thread ); +} + +#endif + +class abstract_thread +{ + public: + virtual ~abstract_thread() {} + virtual void run() = 0; +}; + +template<class T> +class os_thread_func_ptr_deleter +{ + public: + explicit os_thread_func_ptr_deleter(T* p) + : m_p(p) + {} + + T *release() + { T *p = m_p; m_p = 0; return p; } + + T *get() const + { return m_p; } + + T *operator ->() const + { return m_p; } + + ~os_thread_func_ptr_deleter() + { delete m_p; } + + private: + T *m_p; +}; + +#if defined(BOOST_INTERPROCESS_WINDOWS) + +inline unsigned __stdcall launch_thread_routine( void * pv ) +{ + os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) ); + pt->run(); + return 0; +} + +#else + +extern "C" void * launch_thread_routine( void * pv ); + +inline void * launch_thread_routine( void * pv ) +{ + os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) ); + pt->run(); + return 0; +} + +#endif + +template<class F> +class launch_thread_impl + : public abstract_thread +{ + public: + explicit launch_thread_impl( F f ) + : f_( f ) + {} + + void run() + { f_(); } + + private: + F f_; +}; + +template<class F> +inline int thread_launch( OS_thread_t & pt, F f ) +{ + os_thread_func_ptr_deleter<abstract_thread> p( new launch_thread_impl<F>( f ) ); + + int r = thread_create(&pt, launch_thread_routine, p.get()); + if( r == 0 ){ + p.release(); + } + + return r; +} + } //namespace ipcdetail{ } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/detail/pointer_type.hpp b/boost/interprocess/detail/pointer_type.hpp index 549b23fa6c..28b053c2ae 100644 --- a/boost/interprocess/detail/pointer_type.hpp +++ b/boost/interprocess/detail/pointer_type.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // (C) Copyright Gennaro Prota 2003 - 2004. // // Distributed under the Boost Software License, Version 1.0. @@ -14,7 +14,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP #define BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/detail/portable_intermodule_singleton.hpp b/boost/interprocess/detail/portable_intermodule_singleton.hpp index eb2a13e104..80897f2721 100644 --- a/boost/interprocess/detail/portable_intermodule_singleton.hpp +++ b/boost/interprocess/detail/portable_intermodule_singleton.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP #define BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -23,7 +23,7 @@ #include <boost/interprocess/shared_memory_object.hpp> #include <boost/interprocess/detail/atomic.hpp> #include <boost/interprocess/detail/os_thread_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> #include <boost/interprocess/detail/file_locking_helpers.hpp> #include <boost/assert.hpp> @@ -45,16 +45,17 @@ static void create_tmp_subdir_and_get_pid_based_filepath { //Let's create a lock file for each process gmem that will mark if //the process is alive or not - create_tmp_and_clean_old(s); + create_shared_dir_and_clean_old(s); s += "/"; s += subdir_name; if(!open_or_create_directory(s.c_str())){ - throw interprocess_exception(error_info(system_error_code())); + error_info err = system_error_code(); + throw interprocess_exception(err); } s += "/"; s += file_prefix; if(creation_time){ - std::string sstamp; + std::string sstamp; get_pid_creation_time_str(sstamp); s += sstamp; } @@ -137,7 +138,7 @@ struct thread_safe_global_map_dependant<managed_global_memory> delete_file(singleton_lock_file_path_); shared_memory_object::remove(shm_name_); } - + const char * const shm_name_; const char * const singleton_lock_file_path_; managed_global_memory & shm_; @@ -187,7 +188,7 @@ struct thread_safe_global_map_dependant<managed_global_memory> static bool remove_old_gmem() { std::string refcstrRootDirectory; - tmp_folder(refcstrRootDirectory); + get_shared_dir(refcstrRootDirectory); refcstrRootDirectory += "/"; refcstrRootDirectory += get_lock_file_subdir_name(); return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic); @@ -222,11 +223,11 @@ struct thread_safe_global_map_dependant<managed_global_memory> //Create a unique current pid based lock file path create_and_get_singleton_lock_file_path(lck_str); //Open or create and lock file - int fd = open_or_create_and_lock_file(lck_str.c_str()); + int fd_lockfile = open_or_create_and_lock_file(lck_str.c_str()); //If failed, write a bad file descriptor to notify other modules that //something was wrong and unlink shared memory. Mark the function object //to tell caller to retry with another shared memory - if(fd < 0){ + if(fd_lockfile < 0){ this->register_lock_file(GMemMarkToBeRemoved); std::string s; get_map_name(s); @@ -235,7 +236,7 @@ struct thread_safe_global_map_dependant<managed_global_memory> } //If successful, register the file descriptor else{ - this->register_lock_file(fd); + this->register_lock_file(fd_lockfile); } } //If the fd was invalid (maybe a previous try failed) notify caller that @@ -342,7 +343,7 @@ struct thread_safe_global_map_dependant<managed_global_memory> } //namespace intermodule_singleton_helpers { -template<typename C, bool LazyInit = true, bool Phoenix = true> +template<typename C, bool LazyInit = true, bool Phoenix = false> class portable_intermodule_singleton : public intermodule_singleton_impl<C, LazyInit, Phoenix, managed_global_memory> {}; diff --git a/boost/interprocess/detail/posix_time_types_wrk.hpp b/boost/interprocess/detail/posix_time_types_wrk.hpp index e4df85a572..dbde3d1771 100644 --- a/boost/interprocess/detail/posix_time_types_wrk.hpp +++ b/boost/interprocess/detail/posix_time_types_wrk.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP #define BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP +#if defined(_MSC_VER) +# pragma once +#endif + //workaround to avoid winsock redefines when using date-time #ifdef _WIN32 diff --git a/boost/interprocess/detail/preprocessor.hpp b/boost/interprocess/detail/preprocessor.hpp index 47b591c901..06d1354ee1 100644 --- a/boost/interprocess/detail/preprocessor.hpp +++ b/boost/interprocess/detail/preprocessor.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP #define BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -35,7 +35,7 @@ //This cast is ugly but it is necessary until "perfect forwarding" //is achieved in C++0x. Meanwhile, if we want to be able to //bind rvalues with non-const references, we have to be ugly -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \ BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \ //! @@ -45,7 +45,7 @@ //! #endif -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #define BOOST_INTERPROCESS_PP_PARAM(U, u) \ U && u \ //! @@ -55,80 +55,144 @@ //! #endif -#ifndef BOOST_NO_RVALUE_REFERENCES - - #if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - - #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \ - BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \ - //! - - - #else //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \ BOOST_PP_CAT(m_p, n) (::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \ //! - #endif //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - -#else //#ifndef BOOST_NO_RVALUE_REFERENCES +#else //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \ BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \ //! #endif -#define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \ - BOOST_PP_CAT(++m_p, n) \ -//! - -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) + #if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) -#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \ - BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \ -//! + namespace boost { + namespace interprocess { + namespace ipcdetail { + template<class T> + struct ref_holder; + + template<class T> + struct ref_holder<T &> + { + ref_holder(T &t) + : t_(t) + {} + T &t_; + T & get() { return t_; } + T & get_lvalue() { return t_; } + }; + + template<class T> + struct ref_holder<const T> + { + ref_holder(const T &t) + : t_(t) + {} + const T &t_; + const T & get() { return t_; } + const T & get_lvalue() { return t_; } + }; + + template<class T> + struct ref_holder<const T &&> + { + ref_holder(const T &t) + : t_(t) + {} + const T &t_; + const T & get() { return t_; } + const T & get_lvalue() { return t_; } + }; + + template<class T> + struct ref_holder + { + ref_holder(T &&t) + : t_(t) + {} + T &t_; + T && get() { return ::boost::move(t_); } + T & get_lvalue() { return t_; } + }; + + template<class T> + struct ref_holder<T &&> + { + ref_holder(T &&t) + : t(t) + {} + T &t; + T && get() { return ::boost::move(t_); } + T & get_lvalue() { return t_; } + }; + + } //namespace ipcdetail { + } //namespace interprocess { + } //namespace boost { + + #define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \ + ::boost::interprocess::ipcdetail::ref_holder<BOOST_PP_CAT(P, n)> BOOST_PP_CAT(m_p, n); \ + //! + + #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \ + BOOST_PP_CAT(++m_p, n).get_lvalue() \ + //! + + #else //BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG + + #define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data)\ + BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \ + //! + + #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \ + BOOST_PP_CAT(++m_p, n) \ + //! + + #endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) #else + #define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \ + BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \ + //! -#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \ - BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \ -//! - -#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - + #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \ + BOOST_PP_CAT(++m_p, n) \ + //! -#else -#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \ - BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \ -//! #endif #define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \ ::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \ //! -#if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) -#include <boost/container/detail/stored_ref.hpp> + #define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) BOOST_PP_CAT(this->m_p, n).get() \ + //! -#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \ -::boost::container::container_detail::stored_ref< BOOST_PP_CAT(P, n) >::forward( BOOST_PP_CAT(m_p, n) ) \ -//! + #define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \ + BOOST_PP_CAT(*m_p, n).get_lvalue() \ + //! #else -#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \ -::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \ -//! + #define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \ + ::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \ + //! -#endif //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) + #define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \ + BOOST_PP_CAT(*m_p, n) \ + //! -#define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \ -BOOST_PP_CAT(*m_p, n) \ -//! + +#endif //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/detail/ptime_wrk.hpp b/boost/interprocess/detail/ptime_wrk.hpp index 8cda3a445d..87f05e25c2 100644 --- a/boost/interprocess/detail/ptime_wrk.hpp +++ b/boost/interprocess/detail/ptime_wrk.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP #define BOOST_INTERPROCESS_PTIME_WRK_HPP +#if defined(_MSC_VER) +# pragma once +#endif + //workaround to avoid winsock redefines when using date-time #ifdef _WIN32 diff --git a/boost/interprocess/detail/robust_emulation.hpp b/boost/interprocess/detail/robust_emulation.hpp index 1feb42dc35..d586db5071 100644 --- a/boost/interprocess/detail/robust_emulation.hpp +++ b/boost/interprocess/detail/robust_emulation.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2010-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_ROBUST_EMULATION_HPP #define BOOST_INTERPROCESS_ROBUST_EMULATION_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -21,9 +21,12 @@ #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp> #include <boost/interprocess/detail/atomic.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #include <boost/interprocess/detail/intermodule_singleton.hpp> +#include <boost/interprocess/detail/portable_intermodule_singleton.hpp> #include <boost/interprocess/exceptions.hpp> +#include <boost/interprocess/sync/spin/wait.hpp> +#include <boost/interprocess/sync/detail/common_algorithms.hpp> #include <string> namespace boost{ @@ -61,7 +64,7 @@ inline const char *robust_lock_prefix() inline void robust_lock_path(std::string &s) { - tmp_folder(s); + get_shared_dir(s); s += "/"; s += robust_lock_subdir_path(); } @@ -132,7 +135,7 @@ class robust_mutex_lock_file throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: create_file filed with unexpected error"); } } - } + } ~robust_mutex_lock_file() { @@ -197,8 +200,8 @@ class robust_spin_mutex bool lock_own_unique_file(); bool robust_check(); bool check_if_owner_dead_and_take_ownership_atomically(); - bool is_owner_dead(boost::uint32_t owner); - void owner_to_filename(boost::uint32_t owner, std::string &s); + bool is_owner_dead(boost::uint32_t own); + void owner_to_filename(boost::uint32_t own, std::string &s); //The real mutex Mutex mtx; //The pid of the owner @@ -214,42 +217,7 @@ inline robust_spin_mutex<Mutex>::robust_spin_mutex() template<class Mutex> inline void robust_spin_mutex<Mutex>::lock() -{ - //If the mutex is broken (recovery didn't call consistent()), - //then throw an exception - if(atomic_read32(&this->state) == broken_state){ - throw interprocess_exception(lock_error, "Broken id"); - } - - //This function provokes intermodule_singleton instantiation - if(!this->lock_own_unique_file()){ - throw interprocess_exception(lock_error, "Broken id"); - } - - //Now the logic. Try to lock, if successful mark the owner - //if it fails, start recovery logic - unsigned int spin_count = 0; - while(1){ - if (mtx.try_lock()){ - atomic_write32(&this->owner, get_current_process_id()); - break; - } - else{ - //Do the dead owner checking each spin_threshold lock tries - ipcdetail::thread_yield(); - ++spin_count; - if(spin_count > spin_threshold){ - //Check if owner dead and take ownership if possible - if(!this->robust_check()){ - spin_count = 0; - } - else{ - break; - } - } - } - } -} +{ try_based_lock(*this); } template<class Mutex> inline bool robust_spin_mutex<Mutex>::try_lock() @@ -280,38 +248,12 @@ inline bool robust_spin_mutex<Mutex>::try_lock() template<class Mutex> inline bool robust_spin_mutex<Mutex>::timed_lock (const boost::posix_time::ptime &abs_time) -{ - //Same as lock() but with an additional timeout - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - //Obtain current count and target time - boost::posix_time::ptime now = microsec_clock::universal_time(); - - if(now >= abs_time) - return this->try_lock(); - - do{ - if(this->try_lock()){ - break; - } - now = microsec_clock::universal_time(); - - if(now >= abs_time){ - return this->try_lock(); - } - // relinquish current time slice - ipcdetail::thread_yield(); - }while (true); - - return true; -} +{ return try_based_timed_lock(*this, abs_time); } template<class Mutex> -inline void robust_spin_mutex<Mutex>::owner_to_filename(boost::uint32_t owner, std::string &s) +inline void robust_spin_mutex<Mutex>::owner_to_filename(boost::uint32_t own, std::string &s) { - robust_emulation_helpers::create_and_get_robust_lock_file_path(s, owner); + robust_emulation_helpers::create_and_get_robust_lock_file_path(s, own); } template<class Mutex> @@ -324,7 +266,7 @@ inline bool robust_spin_mutex<Mutex>::robust_check() return false; } atomic_write32(&this->state, fixing_state); - return true; + return true; } template<class Mutex> @@ -349,16 +291,16 @@ inline bool robust_spin_mutex<Mutex>::check_if_owner_dead_and_take_ownership_ato } template<class Mutex> -inline bool robust_spin_mutex<Mutex>::is_owner_dead(boost::uint32_t owner) +inline bool robust_spin_mutex<Mutex>::is_owner_dead(boost::uint32_t own) { //If owner is an invalid id, then it's clear it's dead - if(owner == (boost::uint32_t)get_invalid_process_id()){ + if(own == (boost::uint32_t)get_invalid_process_id()){ return true; } //Obtain the lock filename of the owner field std::string file; - this->owner_to_filename(owner, file); + this->owner_to_filename(own, file); //Now the logic is to open and lock it file_handle_t fhnd = open_existing_file(file.c_str(), read_write); @@ -404,7 +346,7 @@ inline bool robust_spin_mutex<Mutex>::previous_owner_dead() { //Notifies if a owner recovery has been performed in the last lock() return atomic_read32(&this->state) == fixing_state; -}; +} template<class Mutex> inline void robust_spin_mutex<Mutex>::unlock() diff --git a/boost/interprocess/detail/segment_manager_helper.hpp b/boost/interprocess/detail/segment_manager_helper.hpp index 2b715d8f5e..1809a8d91a 100644 --- a/boost/interprocess/detail/segment_manager_helper.hpp +++ b/boost/interprocess/detail/segment_manager_helper.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP #define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -32,6 +32,7 @@ #include <string> //char_traits #include <new> //std::nothrow #include <utility> //std::pair +#include <iterator> //std::iterator_traits #include <boost/assert.hpp> //BOOST_ASSERT #include <functional> //unary_function #ifndef BOOST_NO_EXCEPTIONS @@ -72,7 +73,6 @@ class mem_algo_deallocator { if(m_ptr) m_algo.deallocate(m_ptr); } }; -/// @cond template<class size_type> struct block_header { @@ -81,21 +81,18 @@ struct block_header unsigned char m_value_alignment; unsigned char m_alloc_type_sizeof_char; - block_header(size_type value_bytes - ,size_type value_alignment - ,unsigned char alloc_type - ,std::size_t sizeof_char + block_header(size_type val_bytes + ,size_type val_alignment + ,unsigned char al_type + ,std::size_t szof_char ,std::size_t num_char ) - : m_value_bytes(value_bytes) + : m_value_bytes(val_bytes) , m_num_char((unsigned short)num_char) - , m_value_alignment((unsigned char)value_alignment) - , m_alloc_type_sizeof_char - ( (alloc_type << 5u) | - ((unsigned char)sizeof_char & 0x1F) ) + , m_value_alignment((unsigned char)val_alignment) + , m_alloc_type_sizeof_char( (al_type << 5u) | ((unsigned char)szof_char & 0x1F) ) {}; - template<class T> block_header &operator= (const T& ) { return *this; } @@ -118,7 +115,7 @@ struct block_header { return get_rounded_size ( size_type(sizeof(Header)) - , size_type(::boost::alignment_of<block_header<size_type> >::value)) + , size_type(::boost::alignment_of<block_header<size_type> >::value)) + total_size(); } @@ -130,7 +127,7 @@ struct block_header template<class CharType> CharType *name() const - { + { return const_cast<CharType*>(reinterpret_cast<const CharType*> (reinterpret_cast<const char*>(this) + name_offset())); } @@ -175,7 +172,7 @@ struct block_header { return block_header_from_value(value, sizeof(T), ::boost::alignment_of<T>::value); } static block_header<size_type> *block_header_from_value(const void *value, std::size_t sz, std::size_t algn) - { + { block_header * hdr = const_cast<block_header*> (reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(value) - @@ -189,20 +186,20 @@ struct block_header template<class Header> static block_header<size_type> *from_first_header(Header *header) - { + { block_header<size_type> * hdr = reinterpret_cast<block_header<size_type>*>(reinterpret_cast<char*>(header) + - get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value))); + get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value))); //Some sanity checks return hdr; } template<class Header> static Header *to_first_header(block_header<size_type> *bheader) - { + { Header * hdr = reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) - - get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value))); + get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value))); //Some sanity checks return hdr; } @@ -326,6 +323,15 @@ class char_ptr_holder operator const CharType *() { return m_name; } + const CharType *get() const + { return m_name; } + + bool is_unique() const + { return m_name == reinterpret_cast<CharType*>(-1); } + + bool is_anonymous() const + { return m_name == static_cast<CharType*>(0); } + private: const CharType *m_name; }; @@ -350,8 +356,9 @@ struct index_key public: //!Constructor of the key - index_key (const char_type *name, size_type length) - : mp_str(name), m_len(length) {} + index_key (const char_type *nm, size_type length) + : mp_str(nm), m_len(length) + {} //!Less than function for index ordering bool operator < (const index_key & right) const @@ -372,8 +379,8 @@ struct index_key to_raw_pointer(right.mp_str), m_len) == 0; } - void name(const CharT *name) - { mp_str = name; } + void name(const CharT *nm) + { mp_str = nm; } void name_length(size_type len) { m_len = len; } @@ -474,12 +481,12 @@ class segment_manager_iterator_value_adaptor<Iterator, false> template<class Iterator, bool intrusive> struct segment_manager_iterator_transform - : std::unary_function< typename Iterator::value_type + : std::unary_function< typename std::iterator_traits<Iterator>::value_type , segment_manager_iterator_value_adaptor<Iterator, intrusive> > { typedef segment_manager_iterator_value_adaptor<Iterator, intrusive> result_type; - - result_type operator()(const typename Iterator::value_type &arg) const + + result_type operator()(const typename std::iterator_traits<Iterator>::value_type &arg) const { return result_type(arg); } }; diff --git a/boost/interprocess/detail/tmp_dir_helpers.hpp b/boost/interprocess/detail/shared_dir_helpers.hpp index 28e7341406..469ea04ac1 100644 --- a/boost/interprocess/detail/tmp_dir_helpers.hpp +++ b/boost/interprocess/detail/shared_dir_helpers.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2014. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -8,8 +8,12 @@ // ////////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP -#define BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP +#ifndef BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP +#define BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP + +#if defined(_MSC_VER) +# pragma once +#endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -33,7 +37,11 @@ namespace ipcdetail { { windows_bootstamp() { - winapi::get_last_bootup_time(stamp); + //Throw if bootstamp not available + if(!winapi::get_last_bootup_time(stamp)){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } } //Use std::string. Even if this will be constructed in shared memory, all //modules/dlls are from this process so internal raw pointers to heap are always valid @@ -58,7 +66,7 @@ namespace ipcdetail { struct ::timeval result; std::size_t result_len = sizeof result; - if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0) + if (::sysctl (request, 2, &result, &result_len, 0, 0) < 0) return; char bootstamp_str[256]; @@ -90,78 +98,84 @@ namespace ipcdetail { #endif #endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) -inline void get_tmp_base_dir(std::string &tmp_name) +inline void get_shared_dir_root(std::string &dir_path) { #if defined (BOOST_INTERPROCESS_WINDOWS) - winapi::get_shared_documents_folder(tmp_name); - if(tmp_name.empty() || !winapi::is_directory(tmp_name.c_str())){ - tmp_name = get_temporary_path(); - } + winapi::get_shared_documents_folder(dir_path); #else - tmp_name = get_temporary_path(); + dir_path = "/tmp"; #endif - if(tmp_name.empty()){ + //We always need this path, so throw on error + if(dir_path.empty()){ error_info err = system_error_code(); throw interprocess_exception(err); } //Remove final null. - tmp_name += "/boost_interprocess"; + dir_path += "/boost_interprocess"; } -inline void tmp_folder(std::string &tmp_name) +inline void get_shared_dir(std::string &shared_dir) { - get_tmp_base_dir(tmp_name); - #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) - tmp_name += "/"; - get_bootstamp(tmp_name, true); + #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) + shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH; + #else + get_shared_dir_root(shared_dir); + #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) + shared_dir += "/"; + get_bootstamp(shared_dir, true); + #endif #endif } -inline void tmp_filename(const char *filename, std::string &tmp_name) +inline void shared_filepath(const char *filename, std::string &filepath) { - tmp_folder(tmp_name); - tmp_name += "/"; - tmp_name += filename; + get_shared_dir(filepath); + filepath += "/"; + filepath += filename; } -inline void create_tmp_and_clean_old(std::string &tmp_name) +inline void create_shared_dir_and_clean_old(std::string &shared_dir) { - //First get the temp directory - std::string root_tmp_name; - get_tmp_base_dir(root_tmp_name); - - //If fails, check that it's because already exists - if(!create_directory(root_tmp_name.c_str())){ - error_info info(system_error_code()); - if(info.get_error_code() != already_exists_error){ - throw interprocess_exception(info); - } - } - - #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) - tmp_folder(tmp_name); + #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) + shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH; + #else + //First get the temp directory + std::string root_shared_dir; + get_shared_dir_root(root_shared_dir); //If fails, check that it's because already exists - if(!create_directory(tmp_name.c_str())){ + if(!create_directory(root_shared_dir.c_str())){ error_info info(system_error_code()); if(info.get_error_code() != already_exists_error){ throw interprocess_exception(info); } } - //Now erase all old directories created in the previous boot sessions - std::string subdir = tmp_name; - subdir.erase(0, root_tmp_name.size()+1); - delete_subdirectories(root_tmp_name, subdir.c_str()); - #else - tmp_name = root_tmp_name; + + #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) + get_shared_dir(shared_dir); + + //If fails, check that it's because already exists + if(!create_directory(shared_dir.c_str())){ + error_info info(system_error_code()); + if(info.get_error_code() != already_exists_error){ + throw interprocess_exception(info); + } + } + //Now erase all old directories created in the previous boot sessions + std::string subdir = shared_dir; + subdir.erase(0, root_shared_dir.size()+1); + delete_subdirectories(root_shared_dir, subdir.c_str()); + #else + shared_dir = root_shared_dir; + #endif #endif } -inline void create_tmp_and_clean_old_and_get_filename(const char *filename, std::string &tmp_name) +inline void create_shared_dir_cleaning_old_and_get_filepath(const char *filename, std::string &shared_dir) { - create_tmp_and_clean_old(tmp_name); - tmp_name += "/"; - tmp_name += filename; + create_shared_dir_and_clean_old(shared_dir); + shared_dir += "/"; + shared_dir += filename; } inline void add_leading_slash(const char *name, std::string &new_name) @@ -178,4 +192,4 @@ inline void add_leading_slash(const char *name, std::string &new_name) #include <boost/interprocess/detail/config_end.hpp> -#endif //ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP +#endif //ifndef BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP diff --git a/boost/interprocess/detail/transform_iterator.hpp b/boost/interprocess/detail/transform_iterator.hpp index 922c875d6d..5496d19568 100644 --- a/boost/interprocess/detail/transform_iterator.hpp +++ b/boost/interprocess/detail/transform_iterator.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // (C) Copyright Gennaro Prota 2003 - 2004. // // Distributed under the Boost Software License, Version 1.0. @@ -14,7 +14,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP #define BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -61,9 +61,9 @@ template <class Iterator, class UnaryFunction> class transform_iterator : public UnaryFunction , public std::iterator - < typename Iterator::iterator_category + < typename std::iterator_traits<Iterator>::iterator_category , typename ipcdetail::remove_reference<typename UnaryFunction::result_type>::type - , typename Iterator::difference_type + , typename std::iterator_traits<Iterator>::difference_type , operator_arrow_proxy<typename UnaryFunction::result_type> , typename UnaryFunction::result_type> { @@ -115,33 +115,33 @@ class transform_iterator friend bool operator>= (const transform_iterator& i, const transform_iterator& i2) { return !(i < i2); } - friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2) + friend typename std::iterator_traits<Iterator>::difference_type operator- (const transform_iterator& i, const transform_iterator& i2) { return i2.distance_to(i); } //Arithmetic - transform_iterator& operator+=(typename Iterator::difference_type off) + transform_iterator& operator+=(typename std::iterator_traits<Iterator>::difference_type off) { this->advance(off); return *this; } - transform_iterator operator+(typename Iterator::difference_type off) const + transform_iterator operator+(typename std::iterator_traits<Iterator>::difference_type off) const { transform_iterator other(*this); other.advance(off); return other; } - friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right) + friend transform_iterator operator+(typename std::iterator_traits<Iterator>::difference_type off, const transform_iterator& right) { return right + off; } - transform_iterator& operator-=(typename Iterator::difference_type off) + transform_iterator& operator-=(typename std::iterator_traits<Iterator>::difference_type off) { this->advance(-off); return *this; } - transform_iterator operator-(typename Iterator::difference_type off) const + transform_iterator operator-(typename std::iterator_traits<Iterator>::difference_type off) const { return *this + (-off); } typename UnaryFunction::result_type operator*() const { return dereference(); } - typename UnaryFunction::result_type operator[](typename Iterator::difference_type off) const + typename UnaryFunction::result_type operator[](typename std::iterator_traits<Iterator>::difference_type off) const { return UnaryFunction::operator()(m_it[off]); } operator_arrow_proxy<typename UnaryFunction::result_type> @@ -172,10 +172,10 @@ class transform_iterator typename UnaryFunction::result_type dereference() const { return UnaryFunction::operator()(*m_it); } - void advance(typename Iterator::difference_type n) + void advance(typename std::iterator_traits<Iterator>::difference_type n) { std::advance(m_it, n); } - typename Iterator::difference_type distance_to(const transform_iterator &other)const + typename std::iterator_traits<Iterator>::difference_type distance_to(const transform_iterator &other)const { return std::distance(other.m_it, m_it); } }; diff --git a/boost/interprocess/detail/type_traits.hpp b/boost/interprocess/detail/type_traits.hpp index 7a582fee5c..e56a495754 100644 --- a/boost/interprocess/detail/type_traits.hpp +++ b/boost/interprocess/detail/type_traits.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // (C) Copyright John Maddock 2000. -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -13,7 +13,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP #define BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -117,6 +117,12 @@ struct remove_volatile<volatile T> typedef T type; }; +template<class T> +struct remove_const_volatile +{ + typedef typename remove_const<typename remove_volatile<T>::type>::type type; +}; + template <typename T, typename U> struct is_same { @@ -136,6 +142,13 @@ struct is_same static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u)); }; +template<class T, class U> +struct is_cv_same +{ + static const bool value = is_same< typename remove_const_volatile<T>::type + , typename remove_const_volatile<U>::type >::value; +}; + } // namespace ipcdetail } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/detail/utilities.hpp b/boost/interprocess/detail/utilities.hpp index fcb211fb09..351b76cce4 100644 --- a/boost/interprocess/detail/utilities.hpp +++ b/boost/interprocess/detail/utilities.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // (C) Copyright Gennaro Prota 2003 - 2004. // // Distributed under the Boost Software License, Version 1.0. @@ -14,7 +14,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP #define BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -22,7 +22,7 @@ #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/interprocess_fwd.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/type_traits/has_trivial_destructor.hpp> #include <boost/interprocess/detail/min_max.hpp> #include <boost/interprocess/detail/type_traits.hpp> @@ -30,9 +30,11 @@ #include <boost/interprocess/detail/mpl.hpp> #include <boost/interprocess/containers/version_type.hpp> #include <boost/intrusive/pointer_traits.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> +#include <boost/static_assert.hpp> #include <utility> #include <algorithm> +#include <climits> namespace boost { namespace interprocess { @@ -86,7 +88,10 @@ inline SizeType get_truncated_size_po2(SizeType orig_size, SizeType multiple) template <std::size_t OrigSize, std::size_t RoundTo> struct ct_rounded_size { - static const std::size_t value = ((OrigSize-1)/RoundTo+1)*RoundTo; + BOOST_STATIC_ASSERT((RoundTo != 0)); + static const std::size_t intermediate_value = (OrigSize-1)/RoundTo+1; + BOOST_STATIC_ASSERT(intermediate_value <= std::size_t(-1)/RoundTo); + static const std::size_t value = intermediate_value*RoundTo; }; // Gennaro Prota wrote this. Thanks! @@ -133,6 +138,61 @@ addressof(T& v) &const_cast<char&>(reinterpret_cast<const volatile char &>(v))); } +template<class SizeType> +struct sqrt_size_type_max +{ + static const SizeType value = (SizeType(1) << (sizeof(SizeType)*(CHAR_BIT/2)))-1; +}; + +template<class SizeType> +inline bool multiplication_overflows(SizeType a, SizeType b) +{ + const SizeType sqrt_size_max = sqrt_size_type_max<SizeType>::value; + return //Fast runtime check + ( (a | b) > sqrt_size_max && + //Slow division check + b && a > SizeType(-1)/b + ); +} + +template<std::size_t SztSizeOfType, class SizeType> +inline bool size_overflows(SizeType count) +{ + //Compile time-check + BOOST_STATIC_ASSERT(SztSizeOfType <= SizeType(-1)); + //Runtime check + return multiplication_overflows(SizeType(SztSizeOfType), count); +} + +template<class RawPointer> +class pointer_size_t_caster +{ + public: + BOOST_STATIC_ASSERT(sizeof(std::size_t) == sizeof(void*)); + + explicit pointer_size_t_caster(std::size_t sz) + : m_ptr(reinterpret_cast<RawPointer>(sz)) + {} + + explicit pointer_size_t_caster(RawPointer p) + : m_ptr(p) + {} + + std::size_t size() const + { return reinterpret_cast<std::size_t>(m_ptr); } + + RawPointer pointer() const + { return m_ptr; } + + private: + RawPointer m_ptr; +}; + + +template<class SizeType> +inline bool sum_overflows(SizeType a, SizeType b) +{ return SizeType(-1) - a < b; } + //Anti-exception node eraser template<class Cont> class value_eraser @@ -140,7 +200,7 @@ class value_eraser public: value_eraser(Cont & cont, typename Cont::iterator it) : m_cont(cont), m_index_it(it), m_erase(true){} - ~value_eraser() + ~value_eraser() { if(m_erase) m_cont.erase(m_index_it); } void release() { m_erase = false; } diff --git a/boost/interprocess/detail/variadic_templates_tools.hpp b/boost/interprocess/detail/variadic_templates_tools.hpp index 482a0056a7..80154e05d2 100644 --- a/boost/interprocess/detail/variadic_templates_tools.hpp +++ b/boost/interprocess/detail/variadic_templates_tools.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP #define BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/detail/win32_api.hpp b/boost/interprocess/detail/win32_api.hpp index c53725ca3b..d9d3e70330 100644 --- a/boost/interprocess/detail/win32_api.hpp +++ b/boost/interprocess/detail/win32_api.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -8,248 +8,154 @@ // ////////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTERPROCESS_WIN32_PRIMITIVES_HPP -#define BOOST_INTERPROCESS_WIN32_PRIMITIVES_HPP +#ifndef BOOST_INTERPROCESS_WIN32_API_HPP +#define BOOST_INTERPROCESS_WIN32_API_HPP + +#if defined(_MSC_VER) +# pragma once +#endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/date_time/filetime_functions.hpp> #include <cstddef> #include <cstring> -#include <cassert> +#include <cstdlib> +#include <cstdio> + +#include <boost/assert.hpp> #include <string> #include <vector> #include <memory> -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#ifdef BOOST_USE_WINDOWS_H +#include <windows.h> +#include <Wbemidl.h> +#include <Objbase.h> +#include <Shlobj.h> +#endif + +#if defined(_MSC_VER) # pragma once -# pragma comment( lib, "advapi32.lib" ) +# pragma comment( lib, "Advapi32.lib" ) # pragma comment( lib, "oleaut32.lib" ) # pragma comment( lib, "Ole32.lib" ) # pragma comment( lib, "Psapi.lib" ) +# pragma comment( lib, "Shell32.lib" ) //SHGetSpecialFolderPathA #endif -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) # include <cstdarg> # include <boost/detail/interlocked.hpp> #else # error "This file can only be included in Windows OS" #endif +////////////////////////////////////////////////////////////////////////////// +// +// Declaration of Windows structures or typedefs if BOOST_USE_WINDOWS_H is used +// +////////////////////////////////////////////////////////////////////////////// -//The structures used in Interprocess with the -//same binary interface as windows ones -namespace boost { -namespace interprocess { +namespace boost { +namespace interprocess { namespace winapi { -//Some used constants -static const unsigned long infinite_time = 0xFFFFFFFF; -static const unsigned long error_already_exists = 183L; -static const unsigned long error_invalid_handle = 6L; -static const unsigned long error_sharing_violation = 32L; -static const unsigned long error_file_not_found = 2u; -static const unsigned long error_no_more_files = 18u; -//Retries in CreateFile, see http://support.microsoft.com/kb/316609 -static const unsigned int error_sharing_violation_tries = 3u; -static const unsigned int error_sharing_violation_sleep_ms = 250u; -static const unsigned int error_file_too_large = 223u; +//Own defines +static const unsigned long MaxPath = 260; -static const unsigned long semaphore_all_access = (0x000F0000L)|(0x00100000L)|0x3; -static const unsigned long mutex_all_access = (0x000F0000L)|(0x00100000L)|0x0001; +#ifndef BOOST_USE_WINDOWS_H -static const unsigned long page_readonly = 0x02; -static const unsigned long page_readwrite = 0x04; -static const unsigned long page_writecopy = 0x08; +struct GUID_BIPC +{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +}; -static const unsigned long standard_rights_required = 0x000F0000L; -static const unsigned long section_query = 0x0001; -static const unsigned long section_map_write = 0x0002; -static const unsigned long section_map_read = 0x0004; -static const unsigned long section_map_execute = 0x0008; -static const unsigned long section_extend_size = 0x0010; -static const unsigned long section_all_access = standard_rights_required | - section_query | - section_map_write | - section_map_read | - section_map_execute | - section_extend_size; +#if defined(_MSC_VER) +#pragma warning (push) +#pragma warning (disable : 4201) // nonstandard extension used +#endif -static const unsigned long file_map_copy = section_query; -static const unsigned long file_map_write = section_map_write; -static const unsigned long file_map_read = section_map_read; -static const unsigned long file_map_all_access = section_all_access; -static const unsigned long delete_access = 0x00010000L; -static const unsigned long file_flag_backup_semantics = 0x02000000; -static const long file_flag_delete_on_close = 0x04000000; +struct decimal +{ + unsigned short wReserved; + union { + struct { + unsigned char scale; + unsigned char sign; + }; + unsigned short signscale; + }; + unsigned long Hi32; + union { + struct { + unsigned long Lo32; + unsigned long Mid32; + }; + unsigned __int64 Lo64; + }; +}; -//Native API constants -static const unsigned long file_open_for_backup_intent = 0x00004000; -static const int file_share_valid_flags = 0x00000007; -static const long file_delete_on_close = 0x00001000L; -static const long obj_case_insensitive = 0x00000040L; +typedef unsigned short *bstr; -static const unsigned long movefile_copy_allowed = 0x02; -static const unsigned long movefile_delay_until_reboot = 0x04; -static const unsigned long movefile_replace_existing = 0x01; -static const unsigned long movefile_write_through = 0x08; -static const unsigned long movefile_create_hardlink = 0x10; -static const unsigned long movefile_fail_if_not_trackable = 0x20; -static const unsigned long file_share_read = 0x00000001; -static const unsigned long file_share_write = 0x00000002; -static const unsigned long file_share_delete = 0x00000004; +struct wchar_variant +{ + union + { + struct + { + unsigned short vt; + unsigned short wReserved1; + unsigned short wReserved2; + unsigned short wReserved3; + union + { + bstr bstrVal; + struct + { + void* pvRecord; + void* pRecInfo; + }; + }; + }; + decimal decVal; + }; +}; -static const unsigned long file_attribute_readonly = 0x00000001; -static const unsigned long file_attribute_hidden = 0x00000002; -static const unsigned long file_attribute_system = 0x00000004; -static const unsigned long file_attribute_directory = 0x00000010; -static const unsigned long file_attribute_archive = 0x00000020; -static const unsigned long file_attribute_device = 0x00000040; -static const unsigned long file_attribute_normal = 0x00000080; -static const unsigned long file_attribute_temporary = 0x00000100; +#if defined(_MSC_VER) +#pragma warning (pop) +#endif -static const unsigned long generic_read = 0x80000000L; -static const unsigned long generic_write = 0x40000000L; -static const unsigned long wait_object_0 = 0; -static const unsigned long wait_abandoned = 0x00000080L; -static const unsigned long wait_timeout = 258L; -static const unsigned long wait_failed = (unsigned long)0xFFFFFFFF; -static const unsigned long duplicate_close_source = (unsigned long)0x00000001; -static const unsigned long duplicate_same_access = (unsigned long)0x00000002; -static const unsigned long format_message_allocate_buffer - = (unsigned long)0x00000100; -static const unsigned long format_message_ignore_inserts - = (unsigned long)0x00000200; -static const unsigned long format_message_from_string - = (unsigned long)0x00000400; -static const unsigned long format_message_from_hmodule - = (unsigned long)0x00000800; -static const unsigned long format_message_from_system - = (unsigned long)0x00001000; -static const unsigned long format_message_argument_array - = (unsigned long)0x00002000; -static const unsigned long format_message_max_width_mask - = (unsigned long)0x000000FF; -static const unsigned long lang_neutral = (unsigned long)0x00; -static const unsigned long sublang_default = (unsigned long)0x01; -static const unsigned long invalid_file_size = (unsigned long)0xFFFFFFFF; -static const unsigned long invalid_file_attributes = ((unsigned long)-1); -static void * const invalid_handle_value = ((void*)(long)(-1)); -static const unsigned long file_type_char = 0x0002L; -static const unsigned long file_type_disk = 0x0001L; -static const unsigned long file_type_pipe = 0x0003L; -static const unsigned long file_type_remote = 0x8000L; -static const unsigned long file_type_unknown = 0x0000L; -static const unsigned long create_new = 1; -static const unsigned long create_always = 2; -static const unsigned long open_existing = 3; -static const unsigned long open_always = 4; -static const unsigned long truncate_existing = 5; -static const unsigned long file_begin = 0; -static const unsigned long file_current = 1; -static const unsigned long file_end = 2; -static const unsigned long lockfile_fail_immediately = 1; -static const unsigned long lockfile_exclusive_lock = 2; -static const unsigned long error_lock_violation = 33; -static const unsigned long security_descriptor_revision = 1; -//Own defines -static const long SystemTimeOfDayInfoLength = 48; -static const long BootAndSystemstampLength = 16; -static const long BootstampLength = 8; -static const unsigned long MaxPath = 260; -//Keys -static void * const hkey_local_machine = (void*)(unsigned long*)(long)(0x80000002); -static unsigned long key_query_value = 0x0001; -//COM API -const unsigned long RPC_C_AUTHN_LEVEL_PKT_BIPC = 4; -const unsigned long RPC_C_AUTHN_DEFAULT_BIPC = 0xffffffffL; -const unsigned long RPC_C_AUTHZ_DEFAULT_BIPC = 0xffffffffL; -const unsigned long RPC_C_IMP_LEVEL_IMPERSONATE_BIPC = 3; -const signed long EOAC_NONE_BIPC = 0; -const signed long CLSCTX_INPROC_SERVER_BIPC = 0x1; -const signed long CLSCTX_LOCAL_SERVER_BIPC = 0x4; -const signed long WBEM_FLAG_RETURN_IMMEDIATELY_BIPC = 0x10; -const signed long WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC = 0x0; -const signed long WBEM_FLAG_FORWARD_ONLY_BIPC = 0x20; -const signed long WBEM_INFINITE_BIPC = 0xffffffffL; -const signed long RPC_E_TOO_LATE_BIPC = 0x80010119L; -const signed long S_OK_BIPC = 0L; -const signed long S_FALSE_BIPC = 1; -const signed long RPC_E_CHANGED_MODE_BIPC = 0x80010106L; -const unsigned long COINIT_APARTMENTTHREADED_BIPC = 0x2; -const unsigned long COINIT_MULTITHREADED_BIPC = 0x0; -const unsigned long COINIT_DISABLE_OLE1DDE_BIPC = 0x4; -const unsigned long COINIT_SPEED_OVER_MEMORY_BIPC = 0x4; -//If the user needs to change default COM initialization model, -//it can define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL to one of these: -// -// COINIT_APARTMENTTHREADED_BIPC -// COINIT_MULTITHREADED_BIPC -// COINIT_DISABLE_OLE1DDE_BIPC -// COINIT_SPEED_OVER_MEMORY_BIPC -#if !defined(BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL) - #define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL COINIT_APARTMENTTHREADED_BIPC -#elif (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_APARTMENTTHREADED_BIPC) &&\ - (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_MULTITHREADED_BIPC) &&\ - (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_DISABLE_OLE1DDE_BIPC) &&\ - (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_SPEED_OVER_MEMORY_BIPC) - #error "Wrong value for BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL macro" -#endif -} //namespace winapi { -} //namespace interprocess { -} //namespace boost { -namespace boost { -namespace interprocess { -namespace winapi { -struct GUID_BIPC -{ - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; -}; - -const GUID_BIPC CLSID_WbemAdministrativeLocator = - { 0xcb8555cc, 0x9128, 0x11d1, {0xad, 0x9b, 0x00, 0xc0, 0x4f, 0xd8, 0xfd, 0xff}}; - -const GUID_BIPC IID_IUnknown = { 0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; -struct wchar_variant +struct IUnknown_BIPC { - unsigned long long dummy; - union value_t{ - wchar_t *pbstrVal; - unsigned long long dummy; - } value; -}; - - struct IUnknown_BIPC - { - public: - virtual long __stdcall QueryInterface( - /* [in] */ const GUID_BIPC &riid, - /* [iid_is][out] */ void **ppvObject) = 0; - - virtual unsigned long __stdcall AddRef( void) = 0; + public: + virtual long __stdcall QueryInterface( + const GUID_BIPC &riid, // [in] + void **ppvObject) = 0; // [iid_is][out] - virtual unsigned long __stdcall Release( void) = 0; - }; + virtual unsigned long __stdcall AddRef (void) = 0; + virtual unsigned long __stdcall Release(void) = 0; +}; struct IWbemClassObject_BIPC : public IUnknown_BIPC { @@ -258,23 +164,23 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC /* [out] */ void **ppQualSet) = 0; virtual long __stdcall Get( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [unique][in][out] */ wchar_variant *pVal, /* [unique][in][out] */ long *pType, /* [unique][in][out] */ long *plFlavor) = 0; virtual long __stdcall Put( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [in] */ wchar_variant *pVal, /* [in] */ long Type) = 0; virtual long __stdcall Delete( - /* [string][in] */ const wchar_t * wszName) = 0; + /* [string][in] */ const bstr wszName) = 0; virtual long __stdcall GetNames( - /* [string][in] */ const wchar_t * wszQualifierName, + /* [string][in] */ const bstr wszQualifierName, /* [in] */ long lFlags, /* [in] */ wchar_variant *pQualifierVal, /* [out] */ void * *pNames) = 0; @@ -284,7 +190,7 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC virtual long __stdcall Next( /* [in] */ long lFlags, - /* [unique][in][out] */ wchar_t * *strName, + /* [unique][in][out] */ bstr *strName, /* [unique][in][out] */ wchar_variant *pVal, /* [unique][in][out] */ long *pType, /* [unique][in][out] */ long *plFlavor) = 0; @@ -292,7 +198,7 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC virtual long __stdcall EndEnumeration( void) = 0; virtual long __stdcall GetPropertyQualifierSet( - /* [string][in] */ const wchar_t * wszProperty, + /* [string][in] */ const bstr wszProperty, /* [out] */ void **ppQualSet) = 0; virtual long __stdcall Clone( @@ -300,7 +206,7 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC virtual long __stdcall GetObjectText( /* [in] */ long lFlags, - /* [out] */ wchar_t * *pstrObjectText) = 0; + /* [out] */ bstr *pstrObjectText) = 0; virtual long __stdcall SpawnDerivedClass( /* [in] */ long lFlags, @@ -315,49 +221,48 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC /* [in] */ IWbemClassObject_BIPC *pCompareTo) = 0; virtual long __stdcall GetPropertyOrigin( - /* [string][in] */ const wchar_t * wszName, - /* [out] */ wchar_t * *pstrClassName) = 0; + /* [string][in] */ const bstr wszName, + /* [out] */ bstr *pstrClassName) = 0; virtual long __stdcall InheritsFrom( - /* [in] */ const wchar_t * strAncestor) = 0; + /* [in] */ const bstr strAncestor) = 0; virtual long __stdcall GetMethod( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [out] */ IWbemClassObject_BIPC **ppInSignature, /* [out] */ IWbemClassObject_BIPC **ppOutSignature) = 0; virtual long __stdcall PutMethod( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [in] */ IWbemClassObject_BIPC *pInSignature, /* [in] */ IWbemClassObject_BIPC *pOutSignature) = 0; virtual long __stdcall DeleteMethod( - /* [string][in] */ const wchar_t * wszName) = 0; + /* [string][in] */ const bstr wszName) = 0; virtual long __stdcall BeginMethodEnumeration( /* [in] */ long lEnumFlags) = 0; virtual long __stdcall NextMethod( /* [in] */ long lFlags, - /* [unique][in][out] */ wchar_t * *pstrName, + /* [unique][in][out] */ bstr *pstrName, /* [unique][in][out] */ IWbemClassObject_BIPC **ppInSignature, /* [unique][in][out] */ IWbemClassObject_BIPC **ppOutSignature) = 0; virtual long __stdcall EndMethodEnumeration( void) = 0; virtual long __stdcall GetMethodQualifierSet( - /* [string][in] */ const wchar_t * wszMethod, + /* [string][in] */ const bstr wszMethod, /* [out] */ void **ppQualSet) = 0; virtual long __stdcall GetMethodOrigin( - /* [string][in] */ const wchar_t * wszMethodName, - /* [out] */ wchar_t * *pstrClassName) = 0; + /* [string][in] */ const bstr wszMethodName, + /* [out] */ bstr *pstrClassName) = 0; }; - struct IWbemContext_BIPC : public IUnknown_BIPC { public: @@ -373,23 +278,23 @@ public: virtual long __stdcall Next( /* [in] */ long lFlags, - /* [out] */ wchar_t * *pstrName, + /* [out] */ bstr *pstrName, /* [out] */ wchar_variant *pValue) = 0; virtual long __stdcall EndEnumeration( void) = 0; virtual long __stdcall SetValue( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [in] */ wchar_variant *pValue) = 0; virtual long __stdcall GetValue( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [out] */ wchar_variant *pValue) = 0; virtual long __stdcall DeleteValue( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags) = 0; virtual long __stdcall DeleteAll( void) = 0; @@ -425,7 +330,7 @@ struct IWbemServices_BIPC : public IUnknown_BIPC { public: virtual long __stdcall OpenNamespace( - /* [in] */ const wchar_t * strNamespace, + /* [in] */ const bstr strNamespace, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppWorkingNamespace, @@ -439,14 +344,14 @@ public: /* [out] */ void **ppResponseHandler) = 0; virtual long __stdcall GetObject( - /* [in] */ const wchar_t * strObjectPath, + /* [in] */ const bstr strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppObject, /* [unique][in][out] */ void **ppCallResult) = 0; virtual long __stdcall GetObjectAsync( - /* [in] */ const wchar_t * strObjectPath, + /* [in] */ const bstr strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; @@ -464,25 +369,25 @@ public: /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall DeleteClass( - /* [in] */ const wchar_t * strClass, + /* [in] */ const bstr strClass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppCallResult) = 0; virtual long __stdcall DeleteClassAsync( - /* [in] */ const wchar_t * strClass, + /* [in] */ const bstr strClass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall CreateClassEnum( - /* [in] */ const wchar_t * strSuperclass, + /* [in] */ const bstr strSuperclass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [out] */ void **ppEnum) = 0; virtual long __stdcall CreateClassEnumAsync( - /* [in] */ const wchar_t * strSuperclass, + /* [in] */ const bstr strSuperclass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; @@ -500,60 +405,60 @@ public: /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall DeleteInstance( - /* [in] */ const wchar_t * strObjectPath, + /* [in] */ const bstr strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppCallResult) = 0; virtual long __stdcall DeleteInstanceAsync( - /* [in] */ const wchar_t * strObjectPath, + /* [in] */ const bstr strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall CreateInstanceEnum( - /* [in] */ const wchar_t * strFilter, + /* [in] */ const bstr strFilter, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [out] */ void **ppEnum) = 0; virtual long __stdcall CreateInstanceEnumAsync( - /* [in] */ const wchar_t * strFilter, + /* [in] */ const bstr strFilter, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall ExecQuery( - /* [in] */ const wchar_t * strQueryLanguage, - /* [in] */ const wchar_t * strQuery, + /* [in] */ const bstr strQueryLanguage, + /* [in] */ const bstr strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [out] */ IEnumWbemClassObject_BIPC **ppEnum) = 0; virtual long __stdcall ExecQueryAsync( - /* [in] */ const wchar_t * strQueryLanguage, - /* [in] */ const wchar_t * strQuery, + /* [in] */ const bstr strQueryLanguage, + /* [in] */ const bstr strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall ExecNotificationQuery( - /* [in] */ const wchar_t * strQueryLanguage, - /* [in] */ const wchar_t * strQuery, + /* [in] */ const bstr strQueryLanguage, + /* [in] */ const bstr strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [out] */ void **ppEnum) = 0; virtual long __stdcall ExecNotificationQueryAsync( - /* [in] */ const wchar_t * strQueryLanguage, - /* [in] */ const wchar_t * strQuery, + /* [in] */ const bstr strQueryLanguage, + /* [in] */ const bstr strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall ExecMethod( - /* [in] */ const wchar_t * strObjectPath, - /* [in] */ const wchar_t * strMethodName, + /* [in] */ const bstr strObjectPath, + /* [in] */ const bstr strMethodName, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [in] */ IWbemClassObject_BIPC *pInParams, @@ -561,8 +466,8 @@ public: /* [unique][in][out] */ void **ppCallResult) = 0; virtual long __stdcall ExecMethodAsync( - /* [in] */ const wchar_t * strObjectPath, - /* [in] */ const wchar_t * strMethodName, + /* [in] */ const bstr strObjectPath, + /* [in] */ const bstr strMethodName, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [in] */ IWbemClassObject_BIPC *pInParams, @@ -574,19 +479,17 @@ struct IWbemLocator_BIPC : public IUnknown_BIPC { public: virtual long __stdcall ConnectServer( - /* [in] */ const wchar_t * strNetworkResource, - /* [in] */ const wchar_t * strUser, - /* [in] */ const wchar_t * strPassword, - /* [in] */ const wchar_t * strLocale, + /* [in] */ const bstr strNetworkResource, + /* [in] */ const bstr strUser, + /* [in] */ const bstr strPassword, + /* [in] */ const bstr strLocale, /* [in] */ long lSecurityFlags, - /* [in] */ const wchar_t * strAuthority, + /* [in] */ const bstr strAuthority, /* [in] */ void *pCtx, /* [out] */ IWbemServices_BIPC **ppNamespace) = 0; }; - - struct interprocess_overlapped { unsigned long *internal; @@ -602,18 +505,6 @@ struct interprocess_overlapped void *h_event; }; -struct interprocess_semaphore_basic_information -{ - unsigned int count; // current semaphore count - unsigned int limit; // max semaphore count -}; - -struct interprocess_section_basic_information -{ - void * base_address; - unsigned long section_attributes; - __int64 section_size; -}; struct interprocess_filetime { @@ -621,7 +512,7 @@ struct interprocess_filetime unsigned long dwHighDateTime; }; -struct win32_find_data_t +struct win32_find_data { unsigned long dwFileAttributes; interprocess_filetime ftCreationTime; @@ -661,27 +552,16 @@ struct system_info { unsigned short wProcessorRevision; }; -typedef struct _interprocess_memory_basic_information -{ - void * BaseAddress; - void * AllocationBase; - unsigned long AllocationProtect; - unsigned long RegionSize; - unsigned long State; - unsigned long Protect; - unsigned long Type; -} interprocess_memory_basic_information; - -typedef struct _interprocess_acl +struct interprocess_acl { unsigned char AclRevision; unsigned char Sbz1; unsigned short AclSize; unsigned short AceCount; unsigned short Sbz2; -} interprocess_acl; +}; -typedef struct _interprocess_security_descriptor +struct interprocess_security_descriptor { unsigned char Revision; unsigned char Sbz1; @@ -690,59 +570,134 @@ typedef struct _interprocess_security_descriptor void *Group; interprocess_acl *Sacl; interprocess_acl *Dacl; -} interprocess_security_descriptor; +}; -enum file_information_class_t { - file_directory_information = 1, - file_full_directory_information, - file_both_directory_information, - file_basic_information, - file_standard_information, - file_internal_information, - file_ea_information, - file_access_information, - file_name_information, - file_rename_information, - file_link_information, - file_names_information, - file_disposition_information, - file_position_information, - file_full_ea_information, - file_mode_information, - file_alignment_information, - file_all_information, - file_allocation_information, - file_end_of_file_information, - file_alternate_name_information, - file_stream_information, - file_pipe_information, - file_pipe_local_information, - file_pipe_remote_information, - file_mailslot_query_information, - file_mailslot_set_information, - file_compression_information, - file_copy_on_write_information, - file_completion_information, - file_move_cluster_information, - file_quota_information, - file_reparse_point_information, - file_network_open_information, - file_object_id_information, - file_tracking_information, - file_ole_directory_information, - file_content_index_information, - file_inherit_content_index_information, - file_ole_information, - file_maximum_information +struct interprocess_by_handle_file_information +{ + unsigned long dwFileAttributes; + interprocess_filetime ftCreationTime; + interprocess_filetime ftLastAccessTime; + interprocess_filetime ftLastWriteTime; + unsigned long dwVolumeSerialNumber; + unsigned long nFileSizeHigh; + unsigned long nFileSizeLow; + unsigned long nNumberOfLinks; + unsigned long nFileIndexHigh; + unsigned long nFileIndexLow; }; -enum semaphore_information_class { - semaphore_basic_information = 0 +struct interprocess_eventlogrecord +{ + unsigned long Length; // Length of full record + unsigned long Reserved; // Used by the service + unsigned long RecordNumber; // Absolute record number + unsigned long TimeGenerated; // Seconds since 1-1-1970 + unsigned long TimeWritten; // Seconds since 1-1-1970 + unsigned long EventID; + unsigned short EventType; + unsigned short NumStrings; + unsigned short EventCategory; + unsigned short ReservedFlags; // For use with paired events (auditing) + unsigned long ClosingRecordNumber; // For use with paired events (auditing) + unsigned long StringOffset; // Offset from beginning of record + unsigned long UserSidLength; + unsigned long UserSidOffset; + unsigned long DataLength; + unsigned long DataOffset; // Offset from beginning of record + // + // Then follow: + // + // wchar_t SourceName[] + // wchar_t Computername[] + // SID UserSid + // wchar_t Strings[] + // BYTE Data[] + // CHAR Pad[] + // unsigned long Length; + // }; -struct file_name_information_t { - unsigned long FileNameLength; - wchar_t FileName[1]; +union large_integer +{ + __int64 QuadPart; +}; + +struct hinstance_struct { int unused; }; +typedef hinstance_struct *hmodule; + +struct hkey_struct; +typedef hkey_struct *hkey; + +#ifdef _WIN64 +typedef __int64 (__stdcall *farproc_t)(); +#else +typedef int (__stdcall *farproc_t)(); +#endif // _WIN64 + +#else //#ifndef BOOST_USE_WINDOWS_H + +typedef GUID GUID_BIPC; +typedef VARIANT wchar_variant; + +typedef IUnknown IUnknown_BIPC; + +typedef IWbemClassObject IWbemClassObject_BIPC; + +typedef IWbemContext IWbemContext_BIPC; + +typedef IEnumWbemClassObject IEnumWbemClassObject_BIPC; + +typedef IWbemServices IWbemServices_BIPC; + +typedef IWbemLocator IWbemLocator_BIPC; + +typedef OVERLAPPED interprocess_overlapped; + +typedef FILETIME interprocess_filetime; + +typedef WIN32_FIND_DATAA win32_find_data; + +typedef SECURITY_ATTRIBUTES interprocess_security_attributes; + +typedef SYSTEM_INFO system_info; + +typedef ACL interprocess_acl; + +typedef SECURITY_DESCRIPTOR interprocess_security_descriptor; + +typedef BY_HANDLE_FILE_INFORMATION interprocess_by_handle_file_information; + +typedef EVENTLOGRECORD interprocess_eventlogrecord; + +typedef LARGE_INTEGER large_integer; + +typedef HMODULE hmodule; + +typedef HKEY hkey; + +typedef BSTR bstr; + +typedef FARPROC farproc_t; + +#endif //#ifndef BOOST_USE_WINDOWS_H + +////////////////////////////////////////////////////////////////////////////// +// +// Nt native structures +// +////////////////////////////////////////////////////////////////////////////// + +struct interprocess_semaphore_basic_information +{ + unsigned int count; // current semaphore count + unsigned int limit; // max semaphore count +}; + +struct interprocess_section_basic_information +{ + void * base_address; + unsigned long section_attributes; + __int64 section_size; }; struct file_rename_information_t { @@ -785,24 +740,71 @@ union system_timeofday_information __int64 liExpTimeZoneBias; unsigned long uCurrentTimeZoneId; unsigned long dwReserved; + unsigned __int64 ullBootTimeBias; + unsigned __int64 ullSleepTimeBias; } data; - unsigned char Reserved1[SystemTimeOfDayInfoLength]; + unsigned char Reserved1[sizeof(data_t)]; }; -struct interprocess_by_handle_file_information +static const long BootstampLength = sizeof(__int64); +static const long BootAndSystemstampLength = sizeof(__int64)*2; +static const long SystemTimeOfDayInfoLength = sizeof(system_timeofday_information::data_t); + +struct object_name_information_t { - unsigned long dwFileAttributes; - interprocess_filetime ftCreationTime; - interprocess_filetime ftLastAccessTime; - interprocess_filetime ftLastWriteTime; - unsigned long dwVolumeSerialNumber; - unsigned long nFileSizeHigh; - unsigned long nFileSizeLow; - unsigned long nNumberOfLinks; - unsigned long nFileIndexHigh; - unsigned long nFileIndexLow; + unicode_string_t Name; + wchar_t NameBuffer[1]; }; +enum file_information_class_t { + file_directory_information = 1, + file_full_directory_information, + file_both_directory_information, + file_basic_information, + file_standard_information, + file_internal_information, + file_ea_information, + file_access_information, + file_name_information, + file_rename_information, + file_link_information, + file_names_information, + file_disposition_information, + file_position_information, + file_full_ea_information, + file_mode_information, + file_alignment_information, + file_all_information, + file_allocation_information, + file_end_of_file_information, + file_alternate_name_information, + file_stream_information, + file_pipe_information, + file_pipe_local_information, + file_pipe_remote_information, + file_mailslot_query_information, + file_mailslot_set_information, + file_compression_information, + file_copy_on_write_information, + file_completion_information, + file_move_cluster_information, + file_quota_information, + file_reparse_point_information, + file_network_open_information, + file_object_id_information, + file_tracking_information, + file_ole_directory_information, + file_content_index_information, + file_inherit_content_index_information, + file_ole_information, + file_maximum_information +}; + +enum semaphore_information_class { + semaphore_basic_information = 0 +}; + + enum system_information_class { system_basic_information = 0, system_performance_information = 2, @@ -830,11 +832,15 @@ enum section_information_class section_image_information }; -struct object_name_information_t -{ - unicode_string_t Name; - wchar_t NameBuffer[1]; -}; +////////////////////////////////////////////////////////////////////////////// +// +// Forward declaration of winapi +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_USE_WINDOWS_H + +//Kernel32.dll //Some windows API declarations extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId(); @@ -844,6 +850,7 @@ extern "C" __declspec(dllimport) int __stdcall GetProcessTimes , interprocess_filetime *lpExitTime,interprocess_filetime *lpKernelTime , interprocess_filetime *lpUserTime ); extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long); +extern "C" __declspec(dllimport) unsigned long __stdcall GetTickCount(void); extern "C" __declspec(dllimport) int __stdcall SwitchToThread(); extern "C" __declspec(dllimport) unsigned long __stdcall GetLastError(); extern "C" __declspec(dllimport) void __stdcall SetLastError(unsigned long); @@ -855,8 +862,8 @@ extern "C" __declspec(dllimport) int __stdcall DuplicateHandle , unsigned long dwDesiredAccess, int bInheritHandle , unsigned long dwOptions); extern "C" __declspec(dllimport) long __stdcall GetFileType(void *hFile); -extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data_t *lpFindFileData); -extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data_t *lpFindFileData); +extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data *lpFindFileData); +extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data *lpFindFileData); extern "C" __declspec(dllimport) int __stdcall FindClose(void *hFindFile); //extern "C" __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(interprocess_filetime*); //extern "C" __declspec(dllimport) int __stdcall FileTimeToLocalFileTime(const interprocess_filetime *in, const interprocess_filetime *out); @@ -872,12 +879,12 @@ extern "C" __declspec(dllimport) void * __stdcall CreateFileMappingA (void *, in extern "C" __declspec(dllimport) void * __stdcall MapViewOfFileEx (void *, unsigned long, unsigned long, unsigned long, std::size_t, void*); extern "C" __declspec(dllimport) void * __stdcall OpenFileMappingA (unsigned long, int, const char *); extern "C" __declspec(dllimport) void * __stdcall CreateFileA (const char *, unsigned long, unsigned long, struct interprocess_security_attributes*, unsigned long, unsigned long, void *); -extern "C" __declspec(dllimport) int __stdcall DeleteFileA (const char *); -extern "C" __declspec(dllimport) int __stdcall MoveFileExA (const char *, const char *, unsigned long); extern "C" __declspec(dllimport) void __stdcall GetSystemInfo (struct system_info *); extern "C" __declspec(dllimport) int __stdcall FlushViewOfFile (void *, std::size_t); +extern "C" __declspec(dllimport) int __stdcall VirtualUnlock (void *, std::size_t); +extern "C" __declspec(dllimport) int __stdcall VirtualProtect (void *, std::size_t, unsigned long, unsigned long *); extern "C" __declspec(dllimport) int __stdcall FlushFileBuffers (void *); -extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, __int64 *size); +extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, large_integer *size); extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA (unsigned long dwFlags, const void *lpSource, unsigned long dwMessageId, unsigned long dwLanguageId, char *lpBuffer, unsigned long nSize, @@ -890,7 +897,7 @@ extern "C" __declspec(dllimport) int __stdcall GetTempPathA(unsigned long length extern "C" __declspec(dllimport) int __stdcall CreateDirectory(const char *, interprocess_security_attributes*); extern "C" __declspec(dllimport) int __stdcall SetFileValidData(void *, __int64 size); extern "C" __declspec(dllimport) int __stdcall SetEndOfFile(void *); -extern "C" __declspec(dllimport) int __stdcall SetFilePointerEx(void *, __int64 distance, __int64 *new_file_pointer, unsigned long move_method); +extern "C" __declspec(dllimport) int __stdcall SetFilePointerEx(void *, large_integer distance, large_integer *new_file_pointer, unsigned long move_method); extern "C" __declspec(dllimport) int __stdcall LockFile (void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high); extern "C" __declspec(dllimport) int __stdcall UnlockFile(void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high); extern "C" __declspec(dllimport) int __stdcall LockFileEx(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped); @@ -899,18 +906,18 @@ extern "C" __declspec(dllimport) int __stdcall WriteFile(void *hnd, const void * extern "C" __declspec(dllimport) int __stdcall ReadFile(void *hnd, void *buffer, unsigned long bytes_to_read, unsigned long *bytes_read, interprocess_overlapped* overlapped); extern "C" __declspec(dllimport) int __stdcall InitializeSecurityDescriptor(interprocess_security_descriptor *pSecurityDescriptor, unsigned long dwRevision); extern "C" __declspec(dllimport) int __stdcall SetSecurityDescriptorDacl(interprocess_security_descriptor *pSecurityDescriptor, int bDaclPresent, interprocess_acl *pDacl, int bDaclDefaulted); -extern "C" __declspec(dllimport) void *__stdcall LoadLibraryA(const char *); -extern "C" __declspec(dllimport) int __stdcall FreeLibrary(void *); -extern "C" __declspec(dllimport) void *__stdcall GetProcAddress(void *, const char*); -extern "C" __declspec(dllimport) void *__stdcall GetModuleHandleA(const char*); +extern "C" __declspec(dllimport) hmodule __stdcall LoadLibraryA(const char *); +extern "C" __declspec(dllimport) int __stdcall FreeLibrary(hmodule); +extern "C" __declspec(dllimport) farproc_t __stdcall GetProcAddress(void *, const char*); +extern "C" __declspec(dllimport) hmodule __stdcall GetModuleHandleA(const char*); extern "C" __declspec(dllimport) void *__stdcall GetFileInformationByHandle(void *, interprocess_by_handle_file_information*); -extern "C" __declspec(dllimport) unsigned long __stdcall GetMappedFileNameW(void *, void *, wchar_t *, unsigned long); -extern "C" __declspec(dllimport) long __stdcall RegOpenKeyExA(void *, const char *, unsigned long, unsigned long, void **); -extern "C" __declspec(dllimport) long __stdcall RegQueryValueExA(void *, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*); -extern "C" __declspec(dllimport) long __stdcall RegCloseKey(void *); -extern "C" __declspec(dllimport) int __stdcall QueryPerformanceCounter(__int64 *lpPerformanceCount); -//COM API +//Advapi32.dll +extern "C" __declspec(dllimport) long __stdcall RegOpenKeyExA(hkey, const char *, unsigned long, unsigned long, hkey*); +extern "C" __declspec(dllimport) long __stdcall RegQueryValueExA(hkey, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*); +extern "C" __declspec(dllimport) long __stdcall RegCloseKey(hkey); + +//Ole32.dll extern "C" __declspec(dllimport) long __stdcall CoInitializeEx(void *pvReserved, unsigned long dwCoInit); extern "C" __declspec(dllimport) long __stdcall CoInitializeSecurity( void* pSecDesc, @@ -932,18 +939,47 @@ extern "C" __declspec(dllimport) long __stdcall CoInitializeSecurity( unsigned long dwImpLevel, void *pAuthInfo, unsigned long dwCapabilities); - -extern "C" __declspec(dllimport) long __stdcall VariantClear(wchar_variant * pvarg); extern "C" __declspec(dllimport) long __stdcall CoCreateInstance(const GUID_BIPC & rclsid, IUnknown_BIPC *pUnkOuter, unsigned long dwClsContext, const GUID_BIPC & riid, void** ppv); extern "C" __declspec(dllimport) void __stdcall CoUninitialize(void); +//OleAut32.dll +extern "C" __declspec(dllimport) long __stdcall VariantClear(wchar_variant * pvarg); + +//Shell32.dll +extern "C" __declspec(dllimport) int __stdcall SHGetSpecialFolderPathA + (void* hwnd, const char *pszPath, int csidl, int fCreate); + +extern "C" __declspec(dllimport) int __stdcall SHGetFolderPathA(void *hwnd, int csidl, void *hToken, unsigned long dwFlags, const char *pszPath); + +//EventLog access functions +extern "C" __declspec(dllimport) void* __stdcall OpenEventLogA + (const char* lpUNCServerName, const char* lpSourceName); -//API function typedefs -//Pointer to functions +extern "C" __declspec(dllimport) int __stdcall CloseEventLog(void *hEventLog); + +extern "C" __declspec(dllimport) int __stdcall ReadEventLogA + (void *hEventLog, + unsigned long dwReadFlags, + unsigned long dwRecordOffset, + void *lpBuffer, + unsigned long nNumberOfBytesToRead, + unsigned long *pnBytesRead, + unsigned long *pnMinNumberOfBytesNeeded + ); + +#endif //#ifndef BOOST_USE_WINDOWS_H + +//kernel32.dll +typedef int (__stdcall *QueryPerformanceCounter_t) (__int64 *lpPerformanceCount); +typedef int (__stdcall *QueryPerformanceFrequency_t)(__int64 *lpFrequency); + +//ntdll.dll typedef long (__stdcall *NtDeleteFile_t)(object_attributes_t *ObjectAttributes); typedef long (__stdcall *NtSetInformationFile_t)(void *FileHandle, io_status_block_t *IoStatusBlock, void *FileInformation, unsigned long Length, int FileInformationClass ); +typedef long (__stdcall *NtOpenFile)(void **FileHandle, unsigned long DesiredAccess, object_attributes_t *ObjectAttributes + , io_status_block_t *IoStatusBlock, unsigned long ShareAccess, unsigned long Length, unsigned long OpenOptions); typedef long (__stdcall *NtQuerySystemInformation_t)(int, void*, unsigned long, unsigned long *); typedef long (__stdcall *NtQueryObject_t)(void*, object_information_class, void *, unsigned long, unsigned long *); typedef long (__stdcall *NtQuerySemaphore_t)(void*, unsigned int info_class, interprocess_semaphore_basic_information *pinfo, unsigned int info_size, unsigned int *ret_len); @@ -951,19 +987,203 @@ typedef long (__stdcall *NtQuerySection_t)(void*, section_information_class, int typedef long (__stdcall *NtQueryInformationFile_t)(void *,io_status_block_t *,void *, long, int); typedef long (__stdcall *NtOpenFile_t)(void*,unsigned long ,object_attributes_t*,io_status_block_t*,unsigned long,unsigned long); typedef long (__stdcall *NtClose_t) (void*); -typedef long (__stdcall *RtlCreateUnicodeStringFromAsciiz_t)(unicode_string_t *, const char *); -typedef void (__stdcall *RtlFreeUnicodeString_t)(unicode_string_t *); -typedef void (__stdcall *RtlInitUnicodeString_t)( unicode_string_t *, const wchar_t * ); -typedef long (__stdcall *RtlAppendUnicodeToString_t)(unicode_string_t *Destination, const wchar_t *Source); -typedef unsigned long (__stdcall * GetMappedFileName_t)(void *, void *, wchar_t *, unsigned long); -typedef long (__stdcall * RegOpenKeyEx_t)(void *, const char *, unsigned long, unsigned long, void **); -typedef long (__stdcall * RegQueryValueEx_t)(void *, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*); -typedef long (__stdcall * RegCloseKey_t)(void *); +typedef long (__stdcall *NtQueryTimerResolution_t) (unsigned long* LowestResolution, unsigned long* HighestResolution, unsigned long* CurrentResolution); +typedef long (__stdcall *NtSetTimerResolution_t) (unsigned long RequestedResolution, int Set, unsigned long* ActualResolution); + +} //namespace winapi { +} //namespace interprocess { +} //namespace boost { + +////////////////////////////////////////////////////////////////////////////// +// +// Forward declaration of constants +// +////////////////////////////////////////////////////////////////////////////// + +namespace boost { +namespace interprocess { +namespace winapi { + +//Some used constants +static const unsigned long infinite_time = 0xFFFFFFFF; +static const unsigned long error_already_exists = 183L; +static const unsigned long error_invalid_handle = 6L; +static const unsigned long error_sharing_violation = 32L; +static const unsigned long error_file_not_found = 2u; +static const unsigned long error_no_more_files = 18u; +static const unsigned long error_not_locked = 158L; +//Retries in CreateFile, see http://support.microsoft.com/kb/316609 +static const unsigned long error_sharing_violation_tries = 3L; +static const unsigned long error_sharing_violation_sleep_ms = 250L; +static const unsigned long error_file_too_large = 223L; +static const unsigned long error_insufficient_buffer = 122L; +static const unsigned long error_handle_eof = 38L; +static const unsigned long semaphore_all_access = (0x000F0000L)|(0x00100000L)|0x3; +static const unsigned long mutex_all_access = (0x000F0000L)|(0x00100000L)|0x0001; + +static const unsigned long page_readonly = 0x02; +static const unsigned long page_readwrite = 0x04; +static const unsigned long page_writecopy = 0x08; +static const unsigned long page_noaccess = 0x01; + +static const unsigned long standard_rights_required = 0x000F0000L; +static const unsigned long section_query = 0x0001; +static const unsigned long section_map_write = 0x0002; +static const unsigned long section_map_read = 0x0004; +static const unsigned long section_map_execute = 0x0008; +static const unsigned long section_extend_size = 0x0010; +static const unsigned long section_all_access = standard_rights_required | + section_query | + section_map_write | + section_map_read | + section_map_execute | + section_extend_size; + +static const unsigned long file_map_copy = section_query; +static const unsigned long file_map_write = section_map_write; +static const unsigned long file_map_read = section_map_read; +static const unsigned long file_map_all_access = section_all_access; +static const unsigned long delete_access = 0x00010000L; +static const unsigned long file_flag_backup_semantics = 0x02000000; +static const long file_flag_delete_on_close = 0x04000000; + +//Native API constants +static const unsigned long file_open_for_backup_intent = 0x00004000; +static const int file_share_valid_flags = 0x00000007; +static const long file_delete_on_close = 0x00001000L; +static const long obj_case_insensitive = 0x00000040L; +static const long delete_flag = 0x00010000L; + +static const unsigned long movefile_copy_allowed = 0x02; +static const unsigned long movefile_delay_until_reboot = 0x04; +static const unsigned long movefile_replace_existing = 0x01; +static const unsigned long movefile_write_through = 0x08; +static const unsigned long movefile_create_hardlink = 0x10; +static const unsigned long movefile_fail_if_not_trackable = 0x20; + +static const unsigned long file_share_read = 0x00000001; +static const unsigned long file_share_write = 0x00000002; +static const unsigned long file_share_delete = 0x00000004; + +static const unsigned long file_attribute_readonly = 0x00000001; +static const unsigned long file_attribute_hidden = 0x00000002; +static const unsigned long file_attribute_system = 0x00000004; +static const unsigned long file_attribute_directory = 0x00000010; +static const unsigned long file_attribute_archive = 0x00000020; +static const unsigned long file_attribute_device = 0x00000040; +static const unsigned long file_attribute_normal = 0x00000080; +static const unsigned long file_attribute_temporary = 0x00000100; + +static const unsigned long generic_read = 0x80000000L; +static const unsigned long generic_write = 0x40000000L; + +static const unsigned long wait_object_0 = 0; +static const unsigned long wait_abandoned = 0x00000080L; +static const unsigned long wait_timeout = 258L; +static const unsigned long wait_failed = (unsigned long)0xFFFFFFFF; + +static const unsigned long duplicate_close_source = (unsigned long)0x00000001; +static const unsigned long duplicate_same_access = (unsigned long)0x00000002; + +static const unsigned long format_message_allocate_buffer + = (unsigned long)0x00000100; +static const unsigned long format_message_ignore_inserts + = (unsigned long)0x00000200; +static const unsigned long format_message_from_string + = (unsigned long)0x00000400; +static const unsigned long format_message_from_hmodule + = (unsigned long)0x00000800; +static const unsigned long format_message_from_system + = (unsigned long)0x00001000; +static const unsigned long format_message_argument_array + = (unsigned long)0x00002000; +static const unsigned long format_message_max_width_mask + = (unsigned long)0x000000FF; +static const unsigned long lang_neutral = (unsigned long)0x00; +static const unsigned long sublang_default = (unsigned long)0x01; +static const unsigned long invalid_file_size = (unsigned long)0xFFFFFFFF; +static const unsigned long invalid_file_attributes = ((unsigned long)-1); +static void * const invalid_handle_value = ((void*)(long)(-1)); + +static const unsigned long file_type_char = 0x0002L; +static const unsigned long file_type_disk = 0x0001L; +static const unsigned long file_type_pipe = 0x0003L; +static const unsigned long file_type_remote = 0x8000L; +static const unsigned long file_type_unknown = 0x0000L; + +static const unsigned long create_new = 1; +static const unsigned long create_always = 2; +static const unsigned long open_existing = 3; +static const unsigned long open_always = 4; +static const unsigned long truncate_existing = 5; + +static const unsigned long file_begin = 0; +static const unsigned long file_current = 1; +static const unsigned long file_end = 2; + +static const unsigned long lockfile_fail_immediately = 1; +static const unsigned long lockfile_exclusive_lock = 2; +static const unsigned long error_lock_violation = 33; +static const unsigned long security_descriptor_revision = 1; + +const unsigned long max_record_buffer_size = 0x10000L; // 64K +const unsigned long max_path = 260; + +//Keys +static const hkey hkey_local_machine = (hkey)(unsigned long*)(long)(0x80000002); +static unsigned long key_query_value = 0x0001; + +//COM API +const unsigned long RPC_C_AUTHN_LEVEL_PKT_BIPC = 4; +const unsigned long RPC_C_AUTHN_DEFAULT_BIPC = 0xffffffffL; +const unsigned long RPC_C_AUTHZ_DEFAULT_BIPC = 0xffffffffL; +const unsigned long RPC_C_IMP_LEVEL_IMPERSONATE_BIPC = 3; +const signed long EOAC_NONE_BIPC = 0; +const signed long CLSCTX_INPROC_SERVER_BIPC = 0x1; +const signed long CLSCTX_LOCAL_SERVER_BIPC = 0x4; +const signed long WBEM_FLAG_RETURN_IMMEDIATELY_BIPC = 0x10; +const signed long WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC = 0x0; +const signed long WBEM_FLAG_FORWARD_ONLY_BIPC = 0x20; +const signed long WBEM_INFINITE_BIPC = 0xffffffffL; +const signed long RPC_E_TOO_LATE_BIPC = 0x80010119L; +const signed long S_OK_BIPC = 0L; +const signed long S_FALSE_BIPC = 1; +const signed long RPC_E_CHANGED_MODE_BIPC = 0x80010106L; +const unsigned long COINIT_APARTMENTTHREADED_BIPC = 0x2; +const unsigned long COINIT_MULTITHREADED_BIPC = 0x0; +const unsigned long COINIT_DISABLE_OLE1DDE_BIPC = 0x4; +const unsigned long COINIT_SPEED_OVER_MEMORY_BIPC = 0x4; + + +//If the user needs to change default COM initialization model, +//it can define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL to one of these: +// +// COINIT_APARTMENTTHREADED_BIPC +// COINIT_MULTITHREADED_BIPC +// COINIT_DISABLE_OLE1DDE_BIPC +// COINIT_SPEED_OVER_MEMORY_BIPC +#if !defined(BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL) + #define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL COINIT_APARTMENTTHREADED_BIPC +#elif (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_APARTMENTTHREADED_BIPC) &&\ + (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_MULTITHREADED_BIPC) &&\ + (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_DISABLE_OLE1DDE_BIPC) &&\ + (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_SPEED_OVER_MEMORY_BIPC) + #error "Wrong value for BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL macro" +#endif + +const GUID_BIPC CLSID_WbemAdministrativeLocator = + { 0xcb8555cc, 0x9128, 0x11d1, {0xad, 0x9b, 0x00, 0xc0, 0x4f, 0xd8, 0xfd, 0xff}}; + +const GUID_BIPC IID_IUnknown = { 0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; + +static const unsigned long eventlog_sequential_read = 0x0001; +static const unsigned long eventlog_backwards_read = 0x0008; } //namespace winapi { } //namespace interprocess { } //namespace boost { + namespace boost { namespace interprocess { namespace winapi { @@ -993,10 +1213,13 @@ inline unsigned long make_lang_id(unsigned long p, unsigned long s) inline void sched_yield() { if(!SwitchToThread()){ - Sleep(1); + Sleep(0); } } +inline void sleep_tick() +{ Sleep(1); } + inline void sleep(unsigned long ms) { Sleep(ms); } @@ -1015,10 +1238,10 @@ inline unsigned long get_current_process_id() inline unsigned int close_handle(void* handle) { return CloseHandle(handle); } -inline void * find_first_file(const char *lpFileName, win32_find_data_t *lpFindFileData) +inline void * find_first_file(const char *lpFileName, win32_find_data *lpFindFileData) { return FindFirstFileA(lpFileName, lpFindFileData); } -inline bool find_next_file(void *hFindFile, win32_find_data_t *lpFindFileData) +inline bool find_next_file(void *hFindFile, win32_find_data *lpFindFileData) { return FindNextFileA(hFindFile, lpFindFileData) != 0; } inline bool find_close(void *handle) @@ -1033,7 +1256,7 @@ inline bool duplicate_current_process_handle , duplicate_same_access); } -inline long get_file_type(void *hFile) +inline unsigned long get_file_type(void *hFile) { return GetFileType(hFile); } @@ -1125,23 +1348,23 @@ inline void *create_file(const char *name, unsigned long access, unsigned long c return invalid_handle_value; } -inline bool delete_file(const char *name) -{ return 0 != DeleteFileA(name); } - -inline bool move_file_ex(const char *source_filename, const char *destination_filename, unsigned long flags) -{ return 0 != MoveFileExA(source_filename, destination_filename, flags); } - inline void get_system_info(system_info *info) { GetSystemInfo(info); } inline bool flush_view_of_file(void *base_addr, std::size_t numbytes) { return 0 != FlushViewOfFile(base_addr, numbytes); } +inline bool virtual_unlock(void *base_addr, std::size_t numbytes) +{ return 0 != VirtualUnlock(base_addr, numbytes); } + +inline bool virtual_protect(void *base_addr, std::size_t numbytes, unsigned long flNewProtect, unsigned long &lpflOldProtect) +{ return 0 != VirtualProtect(base_addr, numbytes, flNewProtect, &lpflOldProtect); } + inline bool flush_file_buffers(void *handle) { return 0 != FlushFileBuffers(handle); } inline bool get_file_size(void *handle, __int64 &size) -{ return 0 != GetFileSizeEx(handle, &size); } +{ return 0 != GetFileSizeEx(handle, (large_integer*)&size); } inline bool create_directory(const char *name) { @@ -1159,7 +1382,10 @@ inline int set_end_of_file(void *handle) { return 0 != SetEndOfFile(handle); } inline bool set_file_pointer_ex(void *handle, __int64 distance, __int64 *new_file_pointer, unsigned long move_method) -{ return 0 != SetFilePointerEx(handle, distance, new_file_pointer, move_method); } +{ + large_integer d; d.QuadPart = distance; + return 0 != SetFilePointerEx(handle, d, (large_integer*)new_file_pointer, move_method); +} inline bool lock_file_ex(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped) { return 0 != LockFileEx(hnd, flags, reserved, size_low, size_high, overlapped); } @@ -1192,38 +1418,30 @@ inline long interlocked_exchange(long volatile* addend, long value) { return BOOST_INTERLOCKED_EXCHANGE(const_cast<long*>(addend), value); } //Forward functions -inline void *load_library(const char *name) +inline hmodule load_library(const char *name) { return LoadLibraryA(name); } -inline bool free_library(void *module) +inline bool free_library(hmodule module) { return 0 != FreeLibrary(module); } -inline void *get_proc_address(void *module, const char *name) +inline farproc_t get_proc_address(hmodule module, const char *name) { return GetProcAddress(module, name); } inline void *get_current_process() { return GetCurrentProcess(); } -inline void *get_module_handle(const char *name) +inline hmodule get_module_handle(const char *name) { return GetModuleHandleA(name); } -inline unsigned long get_mapped_file_name(void *process, void *lpv, wchar_t *lpfilename, unsigned long nSize) -{ return GetMappedFileNameW(process, lpv, lpfilename, nSize); } - -inline long reg_open_key_ex(void *hKey, const char *lpSubKey, unsigned long ulOptions, unsigned long samDesired, void **phkResult) +inline long reg_open_key_ex(hkey hKey, const char *lpSubKey, unsigned long ulOptions, unsigned long samDesired, hkey *phkResult) { return RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult); } -inline long reg_query_value_ex(void *hKey, const char *lpValueName, unsigned long*lpReserved, unsigned long*lpType, unsigned char *lpData, unsigned long*lpcbData) +inline long reg_query_value_ex(hkey hKey, const char *lpValueName, unsigned long*lpReserved, unsigned long*lpType, unsigned char *lpData, unsigned long*lpcbData) { return RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); } -inline long reg_close_key(void *hKey) +inline long reg_close_key(hkey hKey) { return RegCloseKey(hKey); } -inline bool query_performance_counter(__int64 *lpPerformanceCount) -{ - return 0 != QueryPerformanceCounter(lpPerformanceCount); -} - inline void initialize_object_attributes ( object_attributes_t *pobject_attr, unicode_string_t *name , unsigned long attr, void *rootdir, void *security_descr) @@ -1248,75 +1466,134 @@ inline void rtl_init_empty_unicode_string(unicode_string_t *ucStr, wchar_t *buf, template<int Dummy> struct function_address_holder { - enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NtQuerySemaphore, NtQuerySection, NumFunction }; - enum { NtDll_dll, NumModule }; + enum { NtSetInformationFile + , NtQuerySystemInformation + , NtQueryObject + , NtQuerySemaphore + , NtQuerySection + , NtOpenFile + , NtClose + , NtQueryTimerResolution + , NtSetTimerResolution + , QueryPerformanceCounter + , QueryPerformanceFrequency + , NumFunction + }; + enum { NtDll_dll, Kernel32_dll, NumModule }; private: - static void *FunctionAddresses[NumFunction]; + static const char *FunctionNames[NumFunction]; + static const char *ModuleNames[NumModule]; + static farproc_t FunctionAddresses[NumFunction]; + static unsigned int FunctionModules[NumFunction]; static volatile long FunctionStates[NumFunction]; - static void *ModuleAddresses[NumModule]; + static hmodule ModuleAddresses[NumModule]; static volatile long ModuleStates[NumModule]; - static void *get_module_from_id(unsigned int id) + static hmodule get_module_from_id(unsigned int id) { - assert(id < (unsigned int)NumModule); - const char *module[] = { "ntdll.dll" }; - bool compile_check[sizeof(module)/sizeof(module[0]) == NumModule]; - (void)compile_check; - return get_module_handle(module[id]); + BOOST_ASSERT(id < (unsigned int)NumModule); + hmodule addr = get_module_handle(ModuleNames[id]); + BOOST_ASSERT(addr); + return addr; } - static void *get_module(const unsigned int id) + static hmodule get_module(const unsigned int id) { - assert(id < (unsigned int)NumModule); - while(ModuleStates[id] < 2){ + BOOST_ASSERT(id < (unsigned int)NumModule); + for(unsigned i = 0; ModuleStates[id] < 2; ++i){ if(interlocked_compare_exchange(&ModuleStates[id], 1, 0) == 0){ ModuleAddresses[id] = get_module_from_id(id); interlocked_increment(&ModuleStates[id]); break; } - else{ + else if(i & 1){ sched_yield(); } + else{ + sleep_tick(); + } } return ModuleAddresses[id]; } - static void *get_address_from_dll(const unsigned int id) + static farproc_t get_address_from_dll(const unsigned int id) { - assert(id < (unsigned int)NumFunction); - const char *function[] = { "NtSetInformationFile", "NtQuerySystemInformation", "NtQueryObject", "NtQuerySemaphore", "NtQuerySection" }; - bool compile_check[sizeof(function)/sizeof(function[0]) == NumFunction]; - (void)compile_check; - return get_proc_address(get_module(NtDll_dll), function[id]); + BOOST_ASSERT(id < (unsigned int)NumFunction); + farproc_t addr = get_proc_address(get_module(FunctionModules[id]), FunctionNames[id]); + BOOST_ASSERT(addr); + return addr; } public: - static void *get(const unsigned int id) + static farproc_t get(const unsigned int id) { - assert(id < (unsigned int)NumFunction); - while(FunctionStates[id] < 2){ + BOOST_ASSERT(id < (unsigned int)NumFunction); + for(unsigned i = 0; FunctionStates[id] < 2; ++i){ if(interlocked_compare_exchange(&FunctionStates[id], 1, 0) == 0){ FunctionAddresses[id] = get_address_from_dll(id); interlocked_increment(&FunctionStates[id]); break; } - else{ + else if(i & 1){ sched_yield(); } + else{ + sleep_tick(); + } } return FunctionAddresses[id]; } }; template<int Dummy> -void *function_address_holder<Dummy>::FunctionAddresses[function_address_holder<Dummy>::NumFunction]; +const char *function_address_holder<Dummy>::FunctionNames[function_address_holder<Dummy>::NumFunction] = +{ + "NtSetInformationFile", + "NtQuerySystemInformation", + "NtQueryObject", + "NtQuerySemaphore", + "NtQuerySection", + "NtOpenFile", + "NtClose", + "NtQueryTimerResolution", + "NtSetTimerResolution", + "QueryPerformanceCounter", + "QueryPerformanceFrequency" +}; + +template<int Dummy> +unsigned int function_address_holder<Dummy>::FunctionModules[function_address_holder<Dummy>::NumFunction] = +{ + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + Kernel32_dll, + Kernel32_dll +}; + +template<int Dummy> +const char *function_address_holder<Dummy>::ModuleNames[function_address_holder<Dummy>::NumModule] = +{ + "ntdll.dll", + "kernel32.dll" +}; + + +template<int Dummy> +farproc_t function_address_holder<Dummy>::FunctionAddresses[function_address_holder<Dummy>::NumFunction]; template<int Dummy> volatile long function_address_holder<Dummy>::FunctionStates[function_address_holder<Dummy>::NumFunction]; template<int Dummy> -void *function_address_holder<Dummy>::ModuleAddresses[function_address_holder<Dummy>::NumModule]; +hmodule function_address_holder<Dummy>::ModuleAddresses[function_address_holder<Dummy>::NumModule]; template<int Dummy> volatile long function_address_holder<Dummy>::ModuleStates[function_address_holder<Dummy>::NumModule]; @@ -1329,52 +1606,11 @@ struct dll_func //Complex winapi based functions... struct library_unloader { - void *lib_; - library_unloader(void *module) : lib_(module){} + hmodule lib_; + library_unloader(hmodule module) : lib_(module){} ~library_unloader(){ free_library(lib_); } }; -//pszFilename must have room for at least MaxPath+1 characters -inline bool get_file_name_from_handle_function - (void * hFile, wchar_t *pszFilename, std::size_t length, std::size_t &out_length) -{ - if(length <= MaxPath){ - return false; - } - -// void *hiPSAPI = load_library("PSAPI.DLL"); -// if (0 == hiPSAPI) -// return 0; -// library_unloader unloader(hiPSAPI); - -// Pointer to function getMappedFileName() in PSAPI.DLL -// GetMappedFileName_t pfGMFN = -// (GetMappedFileName_t)get_proc_address(hiPSAPI, "GetMappedFileNameW"); -// if (! pfGMFN){ -// return 0; // Failed: unexpected error -// } - - bool bSuccess = false; - - // Create a file mapping object. - void * hFileMap = create_file_mapping(hFile, page_readonly, 1, 0, 0); - if(hFileMap){ - // Create a file mapping to get the file name. - void* pMem = map_view_of_file_ex(hFileMap, file_map_read, 0, 1, 0); - - if (pMem){ - //out_length = pfGMFN(get_current_process(), pMem, pszFilename, MaxPath); - out_length = get_mapped_file_name(get_current_process(), pMem, pszFilename, MaxPath); - if(out_length){ - bSuccess = true; - } - unmap_view_of_file(pMem); - } - close_handle(hFileMap); - } - - return(bSuccess); -} inline bool get_system_time_of_day_information(system_timeofday_information &info) { @@ -1410,7 +1646,8 @@ inline bool get_boot_and_system_time(unsigned char (&bootsystemstamp) [BootAndSy return true; } -inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s) //will write BootstampLength chars +inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s) + //will write BootstampLength chars { if(s < (BootstampLength*2)) return false; @@ -1431,7 +1668,23 @@ inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s) //will write return true; } -inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t &s) //will write BootAndSystemstampLength chars +//Writes the hexadecimal value of the buffer, in the wide character string. +//str must be twice length +inline void buffer_to_wide_str(const void *buf, std::size_t length, wchar_t *str) +{ + const wchar_t Characters [] = + { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7' + , L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' }; + std::size_t char_counter = 0; + const char *chbuf = static_cast<const char *>(buf); + for(std::size_t i = 0; i != length; ++i){ + str[char_counter++] = Characters[(chbuf[i]&0xF0)>>4]; + str[char_counter++] = Characters[(chbuf[i]&0x0F)]; + } +} + +inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t &s) + //will write BootAndSystemstampLength chars { if(s < (BootAndSystemstampLength*2)) return false; @@ -1440,14 +1693,8 @@ inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t if(!ret){ return false; } - const wchar_t Characters [] = - { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7' - , L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' }; - std::size_t char_counter = 0; - for(std::size_t i = 0; i != static_cast<std::size_t>(BootAndSystemstampLength); ++i){ - bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0xF0)>>4]; - bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0x0F)]; - } + + buffer_to_wide_str(&info.Reserved1[0], BootAndSystemstampLength, bootsystemstamp); s = BootAndSystemstampLength*2; return true; } @@ -1463,16 +1710,99 @@ class handle_closer { close_handle(handle_); } }; +class eventlog_handle_closer +{ + void *handle_; + eventlog_handle_closer(const handle_closer &); + eventlog_handle_closer& operator=(const eventlog_handle_closer &); + public: + explicit eventlog_handle_closer(void *handle) : handle_(handle){} + ~eventlog_handle_closer() + { CloseEventLog(handle_); } +}; + union ntquery_mem_t { object_name_information_t name; struct ren_t { file_rename_information_t info; - wchar_t buf[32767]; + wchar_t buf[1]; } ren; }; +class nt_query_mem_deleter +{ + static const std::size_t rename_offset = offsetof(ntquery_mem_t, ren.info.FileName) - + offsetof(ntquery_mem_t, name.Name.Buffer); + // Timestamp process id atomic count + static const std::size_t rename_suffix = + (SystemTimeOfDayInfoLength + sizeof(unsigned long) + sizeof(boost::uint32_t))*2; + + public: + nt_query_mem_deleter(std::size_t object_name_information_size) + : m_size(object_name_information_size + rename_offset + rename_suffix) + , m_buf(new char [m_size]) + {} + + ~nt_query_mem_deleter() + { + delete[]m_buf; + } + + void realloc_mem(std::size_t num_bytes) + { + num_bytes += rename_suffix + rename_offset; + char *buf = m_buf; + m_buf = new char[num_bytes]; + delete[]buf; + m_size = num_bytes; + } + + ntquery_mem_t *query_mem() const + { return static_cast<ntquery_mem_t *>(static_cast<void*>(m_buf)); } + + unsigned long object_name_information_size() const + { + return static_cast<unsigned long>(m_size - rename_offset - SystemTimeOfDayInfoLength*2); + } + + std::size_t file_rename_information_size() const + { return static_cast<unsigned long>(m_size); } + + private: + std::size_t m_size; + char *m_buf; +}; + +class c_heap_deleter +{ + public: + c_heap_deleter(std::size_t size) + : m_buf(::malloc(size)) + {} + + ~c_heap_deleter() + { + if(m_buf) ::free(m_buf); + } + + void realloc_mem(std::size_t num_bytes) + { + void *buf = ::realloc(m_buf, num_bytes); + if(!buf){ + free(m_buf); + m_buf = 0; + } + } + + void *get() const + { return m_buf; } + + private: + void *m_buf; +}; + inline bool unlink_file(const char *filename) { //Don't try to optimize doing a DeleteFile first @@ -1493,71 +1823,96 @@ inline bool unlink_file(const char *filename) try{ NtSetInformationFile_t pNtSetInformationFile = (NtSetInformationFile_t)dll_func::get(dll_func::NtSetInformationFile); - if(!pNtSetInformationFile){ - return false; - } - NtQueryObject_t pNtQueryObject = - (NtQueryObject_t)dll_func::get(dll_func::NtQueryObject); + NtQueryObject_t pNtQueryObject = (NtQueryObject_t)dll_func::get(dll_func::NtQueryObject); //First step: Obtain a handle to the file using Win32 rules. This resolves relative paths - void *fh = create_file(filename, generic_read | delete_access, open_existing, - file_flag_backup_semantics | file_flag_delete_on_close, 0); + void *fh = create_file(filename, generic_read | delete_access, open_existing, 0, 0); if(fh == invalid_handle_value){ return false; } handle_closer h_closer(fh); + { + //Obtain name length + unsigned long size; + const std::size_t initial_string_mem = 512u; + + nt_query_mem_deleter nt_query_mem(sizeof(ntquery_mem_t)+initial_string_mem); + //Obtain file name with guessed length + if(pNtQueryObject(fh, object_name_information, nt_query_mem.query_mem(), nt_query_mem.object_name_information_size(), &size)){ + //Obtain file name with exact length buffer + nt_query_mem.realloc_mem(size); + if(pNtQueryObject(fh, object_name_information, nt_query_mem.query_mem(), nt_query_mem.object_name_information_size(), &size)){ + return false; + } + } + ntquery_mem_t *pmem = nt_query_mem.query_mem(); + file_rename_information_t *pfri = &pmem->ren.info; + const std::size_t RenMaxNumChars = + (((char*)(pmem) + nt_query_mem.file_rename_information_size()) - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t); + + //Copy filename to the rename member + std::memmove(pmem->ren.info.FileName, pmem->name.Name.Buffer, pmem->name.Name.Length); + std::size_t filename_string_length = pmem->name.Name.Length/sizeof(wchar_t); + + //Search '\\' character to replace from it + for(std::size_t i = filename_string_length; i != 0; --filename_string_length){ + if(pmem->ren.info.FileName[--i] == L'\\') + break; + } - std::auto_ptr<ntquery_mem_t> pmem(new ntquery_mem_t); - file_rename_information_t *pfri = &pmem->ren.info; - const std::size_t RenMaxNumChars = - ((char*)pmem.get() - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t); - - //Obtain file name - unsigned long size; - if(pNtQueryObject(fh, object_name_information, pmem.get(), sizeof(ntquery_mem_t), &size)){ - return false; - } - - //Copy filename to the rename member - std::memmove(pmem->ren.info.FileName, pmem->name.Name.Buffer, pmem->name.Name.Length); - std::size_t filename_string_length = pmem->name.Name.Length/sizeof(wchar_t); - - //Second step: obtain the complete native-nt filename - //if(!get_file_name_from_handle_function(fh, pfri->FileName, RenMaxNumChars, filename_string_length)){ - //return 0; - //} - - //Add trailing mark - if((RenMaxNumChars-filename_string_length) < (SystemTimeOfDayInfoLength*2)){ - return false; - } - - //Search '\\' character to replace it - for(std::size_t i = filename_string_length; i != 0; --filename_string_length){ - if(pmem->ren.info.FileName[--i] == L'\\') - break; - } - - //Add random number - std::size_t s = RenMaxNumChars - filename_string_length; - if(!get_boot_and_system_time_wstr(&pfri->FileName[filename_string_length], s)){ - return false; + //Add random number + std::size_t s = RenMaxNumChars - filename_string_length; + if(!get_boot_and_system_time_wstr(&pfri->FileName[filename_string_length], s)){ + return false; + } + filename_string_length += s; + + //Sometimes the precission of the timestamp is not enough and we need to add another random number. + //The process id (to exclude concurrent processes) and an atomic count (to exclude concurrent threads). + //should be enough + const unsigned long pid = get_current_process_id(); + buffer_to_wide_str(&pid, sizeof(pid), &pfri->FileName[filename_string_length]); + filename_string_length += sizeof(pid)*2; + + static volatile boost::uint32_t u32_count = 0; + interlocked_decrement(reinterpret_cast<volatile long*>(&u32_count)); + buffer_to_wide_str(const_cast<const boost::uint32_t *>(&u32_count), sizeof(boost::uint32_t), &pfri->FileName[filename_string_length]); + filename_string_length += sizeof(boost::uint32_t)*2; + + //Fill rename information (FileNameLength is in bytes) + pfri->FileNameLength = static_cast<unsigned long>(sizeof(wchar_t)*(filename_string_length)); + pfri->Replace = 1; + pfri->RootDir = 0; + + //Cange the name of the in-use file... + io_status_block_t io; + if(0 != pNtSetInformationFile(fh, &io, pfri, nt_query_mem.file_rename_information_size(), file_rename_information)){ + return false; + } } - filename_string_length += s; - - //Fill rename information (FileNameLength is in bytes) - pfri->FileNameLength = static_cast<unsigned long>(sizeof(wchar_t)*(filename_string_length)); - pfri->Replace = 1; - pfri->RootDir = 0; - - //Final step: change the name of the in-use file: - io_status_block_t io; - if(0 != pNtSetInformationFile(fh, &io, pfri, sizeof(ntquery_mem_t::ren_t), file_rename_information)){ - return false; + //...and mark it as delete-on-close + { + //Don't use pNtSetInformationFile with file_disposition_information as it can return STATUS_CANNOT_DELETE + //if the file is still mapped. Reopen it with NtOpenFile and file_delete_on_close + NtOpenFile_t pNtOpenFile = (NtOpenFile_t)dll_func::get(dll_func::NtOpenFile); + NtClose_t pNtClose = (NtClose_t)dll_func::get(dll_func::NtClose); + const wchar_t empty_str [] = L""; + unicode_string_t ustring = { sizeof(empty_str) - sizeof (wchar_t) //length in bytes without null + , sizeof(empty_str) //total size in bytes of memory allocated for Buffer. + , const_cast<wchar_t*>(empty_str) + }; + object_attributes_t object_attr; + initialize_object_attributes(&object_attr, &ustring, 0, fh, 0); + void* fh2 = 0; + io_status_block_t io; + pNtOpenFile( &fh2, delete_flag, &object_attr, &io + , file_share_read | file_share_write | file_share_delete, file_delete_on_close); + pNtClose(fh2); + //Even if NtOpenFile fails, the file was renamed and the original no longer exists, so return a success status + return true; } - return true; } catch(...){ return false; @@ -1567,18 +1922,16 @@ inline bool unlink_file(const char *filename) struct reg_closer { - //reg_closer(RegCloseKey_t func, void *key) : func_(func), key_(key){} - //~reg_closer(){ (*func_)(key_); } - //RegCloseKey_t func_; - void *key_; - reg_closer(void *key) : key_(key){} + hkey key_; + reg_closer(hkey key) : key_(key){} ~reg_closer(){ reg_close_key(key_); } }; inline void get_shared_documents_folder(std::string &s) { + #if 1 //Original registry search code s.clear(); - void *key; + hkey key; if (reg_open_key_ex( hkey_local_machine , "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" , 0 @@ -1602,12 +1955,24 @@ inline void get_shared_documents_folder(std::string &s) (void)err; } } + #else //registry alternative: SHGetSpecialFolderPathA + const int BIPC_CSIDL_COMMON_APPDATA = 0x0023; // All Users\Application Data + const int BIPC_CSIDL_FLAG_CREATE = 0x8000; // new for Win2K, or this in to force creation of folder + const int BIPC_SHGFP_TYPE_CURRENT = 0; // current value for user, verify it exists + + s.clear(); + char szPath[max_path]; + if(0 == SHGetFolderPathA(0, BIPC_CSIDL_COMMON_APPDATA | BIPC_CSIDL_FLAG_CREATE, 0, BIPC_SHGFP_TYPE_CURRENT, szPath)){ + s = szPath; + } + + #endif } inline void get_registry_value(const char *folder, const char *value_key, std::vector<unsigned char> &s) { s.clear(); - void *key; + hkey key; if (reg_open_key_ex( hkey_local_machine , folder , 0 @@ -1700,7 +2065,7 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ IWbemServices_BIPC *pWbemServices = 0; if( 0 != pIWbemLocator->ConnectServer( - bstrNamespace, // Namespace + (bstr)bstrNamespace, // Namespace 0, // Userid 0, // PW 0, // Locale @@ -1738,8 +2103,8 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ IEnumWbemClassObject_BIPC * pEnumObject = 0; if ( 0 != pWbemServices->ExecQuery( - L"WQL", - strValue.c_str(), + (bstr)L"WQL", + (bstr)strValue.c_str(), //WBEM_FLAG_RETURN_IMMEDIATELY_BIPC, WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC | WBEM_FLAG_FORWARD_ONLY_BIPC, 0, @@ -1762,9 +2127,9 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ while( 0 == pEnumObject->Next( WBEM_INFINITE_BIPC, uCount, &pClassObject, &uReturned ) ) { com_releaser<IWbemClassObject_BIPC> IWbemClassObject_releaser(pClassObject); - if ( 0 == pClassObject->Get( L"LastBootUpTime", 0, &vwchar, 0, 0 ) ){ + if ( 0 == pClassObject->Get( (bstr)L"LastBootUpTime", 0, &vwchar, 0, 0 ) ){ bRet = true; - strValue = vwchar.value.pbstrVal; + strValue = (wchar_t*)vwchar.bstrVal; VariantClear(&vwchar ); break; } @@ -1773,6 +2138,10 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ return bRet; } +#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME + +//Obtains the bootup time from WMI LastBootUpTime. +//This time seems to change with hibernation and clock synchronization so avoid it. inline bool get_last_bootup_time( std::wstring& strValue ) { bool ret = get_wmi_class_attribute(strValue, L"Win32_OperatingSystem", L"LastBootUpTime"); @@ -1798,12 +2167,110 @@ inline bool get_last_bootup_time( std::string& str ) return ret; } +#else + +// Loop through the buffer and obtain the contents of the +// requested record in the buffer. +inline bool find_record_in_buffer( const void* pBuffer, unsigned long dwBytesRead, const char *provider_name + , unsigned int id_to_find, interprocess_eventlogrecord *&pevent_log_record) +{ + const unsigned char * pRecord = static_cast<const unsigned char*>(pBuffer); + const unsigned char * pEndOfRecords = pRecord + dwBytesRead; + + while (pRecord < pEndOfRecords){ + interprocess_eventlogrecord *pTypedRecord = (interprocess_eventlogrecord*)pRecord; + // Check provider, written at the end of the fixed-part of the record + if (0 == std::strcmp(provider_name, (char*)(pRecord + sizeof(interprocess_eventlogrecord)))) + { + // Check event id + if(id_to_find == (pTypedRecord->EventID & 0xFFFF)){ + pevent_log_record = pTypedRecord; + return true; + } + } + + pRecord += pTypedRecord->Length; + } + pevent_log_record = 0; + return false; +} + +//Obtains the bootup time from the System Event Log, +//event ID == 6005 (event log started). +//Adapted from http://msdn.microsoft.com/en-us/library/windows/desktop/bb427356.aspx +inline bool get_last_bootup_time(std::string &stamp) +{ + const char *source_name = "System"; + const char *provider_name = "EventLog"; + const unsigned short event_id = 6005u; + + unsigned long status = 0; + unsigned long dwBytesToRead = 0; + unsigned long dwBytesRead = 0; + unsigned long dwMinimumBytesToRead = 0; + + // The source name (provider) must exist as a subkey of Application. + void *hEventLog = OpenEventLogA(0, source_name); + if (hEventLog){ + eventlog_handle_closer hnd_closer(hEventLog); (void)hnd_closer; + // Allocate an initial block of memory used to read event records. The number + // of records read into the buffer will vary depending on the size of each event. + // The size of each event will vary based on the size of the user-defined + // data included with each event, the number and length of insertion + // strings, and other data appended to the end of the event record. + dwBytesToRead = max_record_buffer_size; + c_heap_deleter heap_deleter(dwBytesToRead); + + // Read blocks of records until you reach the end of the log or an + // error occurs. The records are read from newest to oldest. If the buffer + // is not big enough to hold a complete event record, reallocate the buffer. + if (heap_deleter.get() != 0){ + while (0 == status){ + if (!ReadEventLogA(hEventLog, + eventlog_sequential_read | eventlog_backwards_read, + 0, + heap_deleter.get(), + dwBytesToRead, + &dwBytesRead, + &dwMinimumBytesToRead)) { + status = get_last_error(); + if (error_insufficient_buffer == status) { + status = 0; + dwBytesToRead = dwMinimumBytesToRead; + heap_deleter.realloc_mem(dwMinimumBytesToRead); + if (!heap_deleter.get()){ + return false; + } + } + else{ //Not found or EOF + return false; + } + } + else + { + interprocess_eventlogrecord *pTypedRecord; + // Print the contents of each record in the buffer. + if(find_record_in_buffer(heap_deleter.get(), dwBytesRead, provider_name, event_id, pTypedRecord)){ + char stamp_str[sizeof(unsigned long)*3+1]; + std::sprintf(&stamp_str[0], "%u", ((unsigned int)pTypedRecord->TimeGenerated)); + stamp = stamp_str; + break; + } + } + } + } + } + return true; +} + +#endif + inline bool is_directory(const char *path) { - unsigned long attrib = GetFileAttributesA(path); + unsigned long attrib = GetFileAttributesA(path); - return (attrib != invalid_file_attributes && - (attrib & file_attribute_directory)); + return (attrib != invalid_file_attributes && + (attrib & file_attribute_directory)); } inline bool get_file_mapping_size(void *file_mapping_hnd, __int64 &size) @@ -1814,11 +2281,8 @@ inline bool get_file_mapping_size(void *file_mapping_hnd, __int64 &size) interprocess_section_basic_information info; unsigned long ntstatus = pNtQuerySection(file_mapping_hnd, section_basic_information, &info, sizeof(info), 0); - if(ntstatus){ - return false; - } size = info.section_size; - return true; + return !ntstatus; } inline bool get_semaphore_info(void *handle, long &count, long &limit) @@ -1828,14 +2292,41 @@ inline bool get_semaphore_info(void *handle, long &count, long &limit) (winapi::NtQuerySemaphore_t)dll_func::get(winapi::dll_func::NtQuerySemaphore); unsigned int ret_len; long status = pNtQuerySemaphore(handle, winapi::semaphore_basic_information, &info, sizeof(info), &ret_len); - if(status){ - return false; - } count = info.count; limit = info.limit; - return true; + return !status; +} + +inline bool query_timer_resolution(unsigned long *lowres, unsigned long *highres, unsigned long *curres) +{ + winapi::NtQueryTimerResolution_t pNtQueryTimerResolution = + (winapi::NtQueryTimerResolution_t)dll_func::get(winapi::dll_func::NtQueryTimerResolution); + return !pNtQueryTimerResolution(lowres, highres, curres); +} + +inline bool set_timer_resolution(unsigned long RequestedResolution, int Set, unsigned long* ActualResolution) +{ + winapi::NtSetTimerResolution_t pNtSetTimerResolution = + (winapi::NtSetTimerResolution_t)dll_func::get(winapi::dll_func::NtSetTimerResolution); + return !pNtSetTimerResolution(RequestedResolution, Set, ActualResolution); +} + +inline bool query_performance_counter(__int64 *lpPerformanceCount) +{ + QueryPerformanceCounter_t pQueryPerformanceCounter = (QueryPerformanceCounter_t) + dll_func::get(dll_func::QueryPerformanceCounter); + return 0 != pQueryPerformanceCounter(lpPerformanceCount); +} + +inline bool query_performance_frequency(__int64 *lpFrequency) +{ + QueryPerformanceCounter_t pQueryPerformanceFrequency = (QueryPerformanceFrequency_t) + dll_func::get(dll_func::QueryPerformanceFrequency); + return 0 != pQueryPerformanceFrequency(lpFrequency); } +inline unsigned long get_tick_count() +{ return GetTickCount(); } } //namespace winapi } //namespace interprocess @@ -1843,4 +2334,4 @@ inline bool get_semaphore_info(void *handle, long &count, long &limit) #include <boost/interprocess/detail/config_end.hpp> -#endif //#ifdef BOOST_INTERPROCESS_WIN32_PRIMITIVES_HPP +#endif //#ifdef BOOST_INTERPROCESS_WIN32_API_HPP diff --git a/boost/interprocess/detail/windows_intermodule_singleton.hpp b/boost/interprocess/detail/windows_intermodule_singleton.hpp index a716e270a7..58102689da 100644 --- a/boost/interprocess/detail/windows_intermodule_singleton.hpp +++ b/boost/interprocess/detail/windows_intermodule_singleton.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,12 +11,13 @@ #ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP #define BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> +#include <boost/container/string.hpp> #if !defined(BOOST_INTERPROCESS_WINDOWS) #error "This header can't be included from non-windows operating systems" @@ -29,7 +30,7 @@ #include <boost/interprocess/sync/scoped_lock.hpp> #include <boost/cstdint.hpp> #include <string> -#include <map> +#include <boost/container/map.hpp> namespace boost{ namespace interprocess{ @@ -49,7 +50,7 @@ namespace intermodule_singleton_helpers { // max and current semaphore count. class windows_semaphore_based_map { - typedef std::map<std::string, ref_count_ptr> map_type; + typedef boost::container::map<boost::container::string, ref_count_ptr> map_type; public: windows_semaphore_based_map() @@ -68,8 +69,8 @@ class windows_semaphore_based_map //in max_count and initial count parameters. //Also, max count must be bigger than 0 and bigger or equal than initial count. if(sizeof(void*) == sizeof(boost::uint32_t)){ - //This means that for 32 bit processes, a semaphore count (31 usable bits) is - //enough to store 4 byte aligned memory (4GB -> 32 bits - 2 bits = 30 bits). + //This means that for 32 bit processes, a semaphore count (31 usable bits) is + //enough to store 4 byte aligned memory (4GB -> 32 bits - 2 bits = 30 bits). //The max count will hold the pointer value and current semaphore count //will be zero. // @@ -135,6 +136,7 @@ class windows_semaphore_based_map success = success && m_sem_map.open_or_create (name.c_str(), initial_count, max_count, perm, created); if(!success){ + delete m; //winapi_xxx wrappers do the cleanup... throw int(0); } @@ -181,7 +183,7 @@ class windows_semaphore_based_map { scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock); map_type &map = this->get_map_unlocked(); - map_type::iterator it = map.find(std::string(name)); + map_type::iterator it = map.find(boost::container::string(name)); if(it != map.end()){ return &it->second; } @@ -194,7 +196,7 @@ class windows_semaphore_based_map { scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock); map_type &map = this->get_map_unlocked(); - map_type::iterator it = map.insert(map_type::value_type(std::string(name), ref)).first; + map_type::iterator it = map.insert(map_type::value_type(boost::container::string(name), ref)).first; return &it->second; } @@ -202,7 +204,7 @@ class windows_semaphore_based_map { scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock); map_type &map = this->get_map_unlocked(); - return map.erase(std::string(name)) != 0; + return map.erase(boost::container::string(name)) != 0; } template<class F> @@ -217,14 +219,16 @@ class windows_semaphore_based_map scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock); m_sem_count.wait(); if(0 == m_sem_count.value()){ - delete &this->get_map_unlocked(); + map_type &map = this->get_map_unlocked(); + BOOST_ASSERT(map.empty()); + delete ↦ } //First close sems to protect this with the external mutex m_sem_map.close(); m_sem_count.close(); //Once scoped_lock unlocks the mutex, the destructor will close the handle... } - + private: winapi_mutex_wrapper m_mtx_lock; winapi_semaphore_wrapper m_sem_map; @@ -287,7 +291,7 @@ struct thread_safe_global_map_dependant<windows_semaphore_based_map> } //namespace intermodule_singleton_helpers { -template<typename C, bool LazyInit = true, bool Phoenix = true> +template<typename C, bool LazyInit = true, bool Phoenix = false> class windows_intermodule_singleton : public intermodule_singleton_impl < C diff --git a/boost/interprocess/detail/workaround.hpp b/boost/interprocess/detail/workaround.hpp index 884b8680a6..d0456b5053 100644 --- a/boost/interprocess/detail/workaround.hpp +++ b/boost/interprocess/detail/workaround.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,23 +11,46 @@ #ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP #define BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) #define BOOST_INTERPROCESS_WINDOWS #define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION #define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME + //Define this to connect with shared memory created with versions < 1.54 + //#define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME #else #include <unistd.h> #if defined(_POSIX_THREAD_PROCESS_SHARED) && ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0) //Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it. - //Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seems to work. - #if !defined(__CYGWIN__) && !defined(__APPLE__) + #if defined(__CYGWIN__) + #define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED + //Mac Os X < Lion (10.7) might define _POSIX_THREAD_PROCESS_SHARED but there is no real support. + #elif defined(__APPLE__) + #include "TargetConditionals.h" + //Check we're on Mac OS target + #if defined(TARGET_OS_MAC) + #include "AvailabilityMacros.h" + //If minimum target for this compilation is older than Mac Os Lion, then we are out of luck + #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 + #define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED + #endif + #endif + #endif + + //If buggy _POSIX_THREAD_PROCESS_SHARED is detected avoid using it + #if defined(BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED) + #undef BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED + #else #define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED #endif #endif - + #if defined(_POSIX_BARRIERS) && ((_POSIX_BARRIERS - 0) > 0) #define BOOST_INTERPROCESS_POSIX_BARRIERS #endif @@ -39,22 +62,22 @@ #endif //Some platforms have a limited (name length) named semaphore support #elif (defined(__FreeBSD__) && (__FreeBSD__ >= 4)) || defined(__APPLE__) - #define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES + #define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES #endif - #if ((defined _V6_ILP32_OFFBIG) &&(_V6_ILP32_OFFBIG - 0 > 0)) ||\ - ((defined _V6_LP64_OFF64) &&(_V6_LP64_OFF64 - 0 > 0)) ||\ - ((defined _V6_LPBIG_OFFBIG) &&(_V6_LPBIG_OFFBIG - 0 > 0)) ||\ - ((defined _XBS5_ILP32_OFFBIG)&&(_XBS5_ILP32_OFFBIG - 0 > 0)) ||\ - ((defined _XBS5_LP64_OFF64) &&(_XBS5_LP64_OFF64 - 0 > 0)) ||\ - ((defined _XBS5_LPBIG_OFFBIG)&&(_XBS5_LPBIG_OFFBIG - 0 > 0)) ||\ - ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))||\ - ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64)) + #if (defined (_V6_ILP32_OFFBIG) &&(_V6_ILP32_OFFBIG - 0 > 0)) ||\ + (defined (_V6_LP64_OFF64) &&(_V6_LP64_OFF64 - 0 > 0)) ||\ + (defined (_V6_LPBIG_OFFBIG) &&(_V6_LPBIG_OFFBIG - 0 > 0)) ||\ + (defined (_XBS5_ILP32_OFFBIG)&&(_XBS5_ILP32_OFFBIG - 0 > 0)) ||\ + (defined (_XBS5_LP64_OFF64) &&(_XBS5_LP64_OFF64 - 0 > 0)) ||\ + (defined (_XBS5_LPBIG_OFFBIG)&&(_XBS5_LPBIG_OFFBIG - 0 > 0)) ||\ + (defined (_FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))||\ + (defined (_FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64)) #define BOOST_INTERPROCESS_UNIX_64_BIT_OR_BIGGER_OFF_T #endif //Check for XSI shared memory objects. They are available in nearly all UNIX platforms - #if !defined(__QNXNTO__) + #if !defined(__QNXNTO__) && !defined(__ANDROID__) #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS #endif @@ -90,6 +113,8 @@ // hp-ux tru64 vms freebsd #if defined(__hpux) || defined(__osf__) || defined(__vms) || (defined(__FreeBSD__) && (__FreeBSD__ < 7)) #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY + //Some systems have "jailed" environments where shm usage is restricted at runtime + //and temporary file file based shm is possible in those executions. #elif defined(__FreeBSD__) #define BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY #endif @@ -108,6 +133,10 @@ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) #define BOOST_INTERPROCESS_BSD_DERIVATIVE + //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas + //others (FreeBSD & Darwin) need sys/types.h + #include <sys/types.h> + #include <sys/param.h> #include <sys/sysctl.h> #if defined(CTL_KERN) && defined (KERN_BOOTTIME) //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME @@ -115,7 +144,7 @@ #endif #endif //!defined(BOOST_INTERPROCESS_WINDOWS) -#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES) +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #define BOOST_INTERPROCESS_PERFECT_FORWARDING #endif @@ -130,6 +159,44 @@ #define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000 #endif +//Other switches +//BOOST_INTERPROCESS_MSG_QUEUE_USES_CIRC_INDEX +//message queue uses a circular queue as index instead of an array (better performance) +//Boost version < 1.52 uses an array, so undef this if you want to communicate +//with processes compiled with those versions. +#define BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + +//Inline attributes +#if defined(_MSC_VER) + #define BOOST_INTERPROCESS_ALWAYS_INLINE __forceinline +#elif defined (__GNUC__) + #define BOOST_INTERPROCESS_ALWAYS_INLINE __attribute__((__always_inline__)) +#else + #define BOOST_INTERPROCESS_ALWAYS_INLINE inline +#endif + +#if defined(_MSC_VER) + #define BOOST_INTERPROCESS_NEVER_INLINE __declspec(noinline) +#elif defined (__GNUC__) + #define BOOST_INTERPROCESS_NEVER_INLINE __attribute__((__noinline__)) +#endif + +//Macros for documentation purposes. For code, expands to the argument +#define BOOST_INTERPROCESS_IMPDEF(TYPE) TYPE +#define BOOST_INTERPROCESS_SEEDOC(TYPE) TYPE + +#if defined(BOOST_NO_CXX11_NOEXCEPT) + #if defined(BOOST_MSVC) + #define BOOST_INTERPROCESS_NOEXCEPT throw() + #else + #define BOOST_INTERPROCESS_NOEXCEPT + #endif + #define BOOST_INTERPROCESS_NOEXCEPT_IF(x) +#else + #define BOOST_INTERPROCESS_NOEXCEPT noexcept + #define BOOST_INTERPROCESS_NOEXCEPT_IF(x) noexcept(x) +#endif + #include <boost/interprocess/detail/config_end.hpp> #endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP diff --git a/boost/interprocess/detail/xsi_shared_memory_device.hpp b/boost/interprocess/detail/xsi_shared_memory_device.hpp index ef4b009bc1..5bb077179a 100644 --- a/boost/interprocess/detail/xsi_shared_memory_device.hpp +++ b/boost/interprocess/detail/xsi_shared_memory_device.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/detail/workaround.hpp> @@ -23,7 +27,7 @@ #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/detail/utilities.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #include <boost/interprocess/interprocess_fwd.hpp> #include <boost/interprocess/exceptions.hpp> @@ -44,9 +48,9 @@ namespace interprocess { class xsi_shared_memory_device { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: @@ -74,10 +78,10 @@ class xsi_shared_memory_device { this->swap(moved); } xsi_shared_memory_device &operator=(BOOST_RV_REF(xsi_shared_memory_device) moved) - { + { xsi_shared_memory_device tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps two xsi_shared_memory_device. Does not throw @@ -113,7 +117,7 @@ class xsi_shared_memory_device //!Returns false on error. Never throws static bool remove(int shmid); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: template<int Dummy> struct info_constants_t @@ -147,7 +151,7 @@ class xsi_shared_memory_device xsi_shared_memory m_shm; mode_t m_mode; std::string m_name; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; template<int Dummy> @@ -162,7 +166,7 @@ const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::LastID; template<int Dummy> const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::NumID; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline xsi_shared_memory_device::xsi_shared_memory_device() : m_shm(), m_mode(invalid_mode), m_name() @@ -178,7 +182,7 @@ inline void xsi_shared_memory_device::swap(xsi_shared_memory_device &other) { m_shm.swap(other.m_shm); std::swap(m_mode, other.m_mode); - m_name.swap(other.m_name); + m_name.swap(other.m_name); } inline mapping_handle_t xsi_shared_memory_device::get_mapping_handle() const @@ -197,7 +201,7 @@ inline void xsi_shared_memory_device::priv_obtain_index permissions p; p.set_unrestricted(); std::string xsi_shm_emulation_file_path; - ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, xsi_shm_emulation_file_path); + ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, xsi_shm_emulation_file_path); ipcdetail::create_or_open_file(xsi_shm_emulation_file_path.c_str(), read_write, p); const std::size_t MemSize = sizeof(info_t); @@ -382,7 +386,7 @@ inline bool xsi_shared_memory_device::remove(const char *shmname) inline bool xsi_shared_memory_device::remove(int shmid) { return xsi_shared_memory::remove(shmid); } -///@endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp b/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp index 14811e7e62..d1c71d55f5 100644 --- a/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp +++ b/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/detail/workaround.hpp> @@ -23,7 +27,7 @@ #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/detail/utilities.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #include <boost/interprocess/interprocess_fwd.hpp> #include <boost/interprocess/exceptions.hpp> @@ -38,22 +42,22 @@ namespace interprocess { class xsi_shared_memory_file_wrapper : public xsi_shared_memory { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: xsi_shared_memory_file_wrapper() : xsi_shared_memory() {} - xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions()) + xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t , std::size_t size, const permissions& perm = permissions()) : xsi_shared_memory(create_only_t(), key, size, perm.get_permissions()) {} - xsi_shared_memory_file_wrapper(open_or_create_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions()) + xsi_shared_memory_file_wrapper(open_or_create_t, const xsi_key &key, mode_t , std::size_t size, const permissions& perm = permissions()) : xsi_shared_memory(open_or_create_t(), key, size, perm.get_permissions()) {} - xsi_shared_memory_file_wrapper(open_only_t, const xsi_key &key, mode_t mode, const permissions& perm = permissions()) + xsi_shared_memory_file_wrapper(open_only_t, const xsi_key &key, mode_t, const permissions& = permissions()) : xsi_shared_memory(open_only_t(), key) {} @@ -61,10 +65,10 @@ class xsi_shared_memory_file_wrapper { this->swap(moved); } xsi_shared_memory_file_wrapper &operator=(BOOST_RV_REF(xsi_shared_memory_file_wrapper) moved) - { + { xsi_shared_memory_file_wrapper tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps two xsi_shared_memory_file_wrapper. Does not throw diff --git a/boost/interprocess/errors.hpp b/boost/interprocess/errors.hpp index 9eed55a29b..6d4572f718 100644 --- a/boost/interprocess/errors.hpp +++ b/boost/interprocess/errors.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -24,7 +24,7 @@ #ifndef BOOST_INTERPROCESS_ERRORS_HPP #define BOOST_INTERPROCESS_ERRORS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -33,7 +33,7 @@ #include <stdarg.h> #include <string> -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) # include <boost/interprocess/detail/win32_api.hpp> #else # ifdef BOOST_HAS_UNISTD_H @@ -42,17 +42,17 @@ # else //ifdef BOOST_HAS_UNISTD_H # error Unknown platform # endif //ifdef BOOST_HAS_UNISTD_H -#endif //#if (defined BOOST_INTERPROCESS_WINDOWS) +#endif //#if defined (BOOST_INTERPROCESS_WINDOWS) //!\file //!Describes the error numbering of interprocess classes namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline int system_error_code() // artifact of POSIX and WINDOWS error reporting { - #if (defined BOOST_INTERPROCESS_WINDOWS) + #if defined (BOOST_INTERPROCESS_WINDOWS) return winapi::get_last_error(); #else return errno; // GCC 3.1 won't accept ::errno @@ -60,7 +60,7 @@ inline int system_error_code() // artifact of POSIX and WINDOWS error reporting } -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) inline void fill_system_message(int sys_err_code, std::string &str) { void *lpMsgBuf; @@ -85,7 +85,7 @@ inline void fill_system_message(int sys_err_code, std::string &str) inline void fill_system_message( int system_error, std::string &str) { str = std::strerror(system_error); } # endif -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED enum error_code_t { @@ -115,11 +115,12 @@ enum error_code_t invalid_argument, timeout_when_locking_error, timeout_when_waiting_error, + owner_dead_error }; typedef int native_error_t; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) struct ec_xlate { native_error_t sys_ec; @@ -128,7 +129,7 @@ struct ec_xlate static const ec_xlate ec_table[] = { - #if (defined BOOST_INTERPROCESS_WINDOWS) + #if defined (BOOST_INTERPROCESS_WINDOWS) { /*ERROR_ACCESS_DENIED*/5L, security_error }, { /*ERROR_INVALID_ACCESS*/12L, security_error }, { /*ERROR_SHARING_VIOLATION*/32L, security_error }, @@ -161,7 +162,7 @@ static const ec_xlate ec_table[] = { /*ERROR_NOT_ENOUGH_MEMORY*/8L, out_of_memory_error }, { /*ERROR_TOO_MANY_OPEN_FILES*/4L, out_of_resource_error }, { /*ERROR_INVALID_ADDRESS*/487L, busy_error } - #else //#if (defined BOOST_INTERPROCESS_WINDOWS) + #else //#if defined (BOOST_INTERPROCESS_WINDOWS) { EACCES, security_error }, { EROFS, read_only_error }, { EIO, io_error }, @@ -179,11 +180,11 @@ static const ec_xlate ec_table[] = { EMFILE, out_of_resource_error }, { ENOENT, not_such_file_or_directory }, { EINVAL, invalid_argument } - #endif //#if (defined BOOST_INTERPROCESS_WINDOWS) + #endif //#if defined (BOOST_INTERPROCESS_WINDOWS) }; inline error_code_t lookup_error(native_error_t err) -{ +{ const ec_xlate *cur = &ec_table[0], *end = cur + sizeof(ec_table)/sizeof(ec_xlate); for (;cur != end; ++cur ){ @@ -226,7 +227,7 @@ struct error_info native_error_t m_nat; error_code_t m_ec; }; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } // namespace interprocess { } // namespace boost diff --git a/boost/interprocess/exceptions.hpp b/boost/interprocess/exceptions.hpp index a4f196f0be..36e5e2ca5b 100644 --- a/boost/interprocess/exceptions.hpp +++ b/boost/interprocess/exceptions.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_EXCEPTIONS_HPP #define BOOST_INTERPROCESS_EXCEPTIONS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -75,11 +75,11 @@ class interprocess_exception : public std::exception // Note: a value of other_error implies a library (rather than system) error error_code_t get_error_code() const { return m_err.get_error_code(); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: error_info m_err; std::string m_str; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!This is the exception thrown by shared interprocess_mutex family when a deadlock situation diff --git a/boost/interprocess/file_mapping.hpp b/boost/interprocess/file_mapping.hpp index 2a4e4cca00..935260354f 100644 --- a/boost/interprocess/file_mapping.hpp +++ b/boost/interprocess/file_mapping.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_FILE_MAPPING_HPP #define BOOST_INTERPROCESS_FILE_MAPPING_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -19,7 +23,7 @@ #include <boost/interprocess/detail/utilities.hpp> #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <string> //std::string //!\file @@ -32,9 +36,9 @@ namespace interprocess { //!create mapped regions from the mapped files class file_mapping { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) BOOST_MOVABLE_BUT_NOT_COPYABLE(file_mapping) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructs an empty file mapping. @@ -52,6 +56,7 @@ class file_mapping //!Does not throw file_mapping(BOOST_RV_REF(file_mapping) moved) : m_handle(file_handle_t(ipcdetail::invalid_file())) + , m_mode(read_only) { this->swap(moved); } //!Moves the ownership of "moved"'s file mapping to *this. @@ -61,7 +66,7 @@ class file_mapping { file_mapping tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps to file_mappings. @@ -90,18 +95,19 @@ class file_mapping //!being used other processes and no deletion permission was shared. static bool remove(const char *filename); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //!Closes a previously opened file mapping. Never throws. void priv_close(); file_handle_t m_handle; - mode_t m_mode; - std::string m_filename; - /// @endcond + mode_t m_mode; + std::string m_filename; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; inline file_mapping::file_mapping() : m_handle(file_handle_t(ipcdetail::invalid_file())) + , m_mode(read_only) {} inline file_mapping::~file_mapping() @@ -111,10 +117,10 @@ inline const char *file_mapping::get_name() const { return m_filename.c_str(); } inline void file_mapping::swap(file_mapping &other) -{ +{ std::swap(m_handle, other.m_handle); std::swap(m_mode, other.m_mode); - m_filename.swap(other.m_filename); + m_filename.swap(other.m_filename); } inline mapping_handle_t file_mapping::get_mapping_handle() const @@ -148,7 +154,7 @@ inline file_mapping::file_mapping inline bool file_mapping::remove(const char *filename) { return ipcdetail::delete_file(filename); } -///@cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline void file_mapping::priv_close() { @@ -158,8 +164,6 @@ inline void file_mapping::priv_close() } } -///@endcond - //!A class that stores the name of a file //!and tries to remove it in its destructor //!Useful to remove temporary files in the presence @@ -176,6 +180,8 @@ class remove_file_on_destroy { ipcdetail::delete_file(m_name); } }; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/indexes/flat_map_index.hpp b/boost/interprocess/indexes/flat_map_index.hpp index bac387e268..4307dedb0e 100644 --- a/boost/interprocess/indexes/flat_map_index.hpp +++ b/boost/interprocess/indexes/flat_map_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -10,6 +10,10 @@ #ifndef BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP #define BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -25,6 +29,8 @@ //[flat_map_index namespace boost { namespace interprocess { +#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + //!Helper class to define typedefs from IndexTraits template <class MapConfig> struct flat_map_index_aux @@ -41,6 +47,8 @@ struct flat_map_index_aux key_less, allocator_type> index_t; }; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + //!Index type based in flat_map. Just derives from flat_map and //!defines the interface needed by managed memory segments. template <class MapConfig> @@ -48,12 +56,12 @@ class flat_map_index //Derive class from flat_map specialization : public flat_map_index_aux<MapConfig>::index_t { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef flat_map_index_aux<MapConfig> index_aux; typedef typename index_aux::index_t base_type; typedef typename index_aux:: segment_manager_base segment_manager_base; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Takes a pointer to the segment manager. Can throw diff --git a/boost/interprocess/indexes/iset_index.hpp b/boost/interprocess/indexes/iset_index.hpp index 8fc91466f3..170e5dac1b 100644 --- a/boost/interprocess/indexes/iset_index.hpp +++ b/boost/interprocess/indexes/iset_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_ISET_INDEX_HPP #define BOOST_INTERPROCESS_ISET_INDEX_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -28,7 +32,7 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Helper class to define typedefs from IndexTraits template <class MapConfig> @@ -52,7 +56,7 @@ struct iset_index_aux , bi::base_hook<derivation_hook> >::type index_t; }; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Index type based in boost::intrusive::set. //!Just derives from boost::intrusive::set @@ -62,13 +66,13 @@ class iset_index //Derive class from map specialization : public iset_index_aux<MapConfig>::index_t { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef iset_index_aux<MapConfig> index_aux; typedef typename index_aux::index_t index_type; typedef typename MapConfig:: intrusive_compare_key_type intrusive_compare_key_type; typedef typename MapConfig::char_type char_type; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: typedef typename index_type::iterator iterator; @@ -76,13 +80,13 @@ class iset_index typedef typename index_type::insert_commit_data insert_commit_data; typedef typename index_type::value_type value_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: struct intrusive_key_value_less { bool operator()(const intrusive_compare_key_type &i, const value_type &b) const - { + { std::size_t blen = b.name_length(); return (i.m_len < blen) || (i.m_len == blen && @@ -91,7 +95,7 @@ class iset_index } bool operator()(const value_type &b, const intrusive_compare_key_type &i) const - { + { std::size_t blen = b.name_length(); return (blen < i.m_len) || (blen == i.m_len && @@ -100,7 +104,7 @@ class iset_index } }; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: @@ -130,7 +134,7 @@ class iset_index { return index_type::insert_check(key, intrusive_key_value_less(), commit_data); } }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Trait class to detect if an index is an intrusive //!index. @@ -140,7 +144,7 @@ struct is_intrusive_index { static const bool value = true; }; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost diff --git a/boost/interprocess/indexes/iunordered_set_index.hpp b/boost/interprocess/indexes/iunordered_set_index.hpp index 3c5f85526c..c85c557c25 100644 --- a/boost/interprocess/indexes/iunordered_set_index.hpp +++ b/boost/interprocess/indexes/iunordered_set_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP #define BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -28,7 +32,7 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Helper class to define typedefs //!from IndexTraits @@ -58,21 +62,21 @@ struct iunordered_set_index_aux struct equal_function { bool operator()(const intrusive_compare_key_type &i, const value_type &b) const - { + { return (i.m_len == b.name_length()) && (std::char_traits<char_type>::compare (i.mp_str, b.name(), i.m_len) == 0); } bool operator()(const value_type &b, const intrusive_compare_key_type &i) const - { + { return (i.m_len == b.name_length()) && (std::char_traits<char_type>::compare (i.mp_str, b.name(), i.m_len) == 0); } bool operator()(const value_type &b1, const value_type &b2) const - { + { return (b1.name_length() == b2.name_length()) && (std::char_traits<char_type>::compare (b1.name(), b2.name(), b1.name_length()) == 0); @@ -116,7 +120,7 @@ struct iunordered_set_index_aux bucket_type init_bucket; }; }; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Index type based in boost::intrusive::set. //!Just derives from boost::intrusive::set @@ -127,7 +131,7 @@ class iunordered_set_index : private iunordered_set_index_aux<MapConfig>::allocator_holder , public iunordered_set_index_aux<MapConfig>::index_t { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef iunordered_set_index_aux<MapConfig> index_aux; typedef typename index_aux::index_t index_type; typedef typename MapConfig:: @@ -139,7 +143,7 @@ class iunordered_set_index iunordered_set_index_aux<MapConfig>::allocator_type allocator_type; typedef typename iunordered_set_index_aux<MapConfig>::allocator_holder allocator_holder; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: typedef typename index_type::iterator iterator; @@ -151,7 +155,7 @@ class iunordered_set_index typedef typename index_type::bucket_traits bucket_traits; typedef typename index_type::size_type size_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef typename index_aux:: segment_manager_base segment_manager_base; @@ -190,7 +194,7 @@ class iunordered_set_index bucket_ptr shunk_p = alloc.allocation_command (boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, received_size, received_size, received_size, buckets).first; - BOOST_ASSERT(buckets == shunk_p); + BOOST_ASSERT(buckets == shunk_p); (void)shunk_p; bucket_ptr buckets_init = buckets + received_size; for(size_type i = 0; i < (old_size - received_size); ++i){ @@ -236,7 +240,7 @@ class iunordered_set_index iunordered_set_index<MapConfig>* get_this_pointer() { return this; } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Takes a pointer to the @@ -290,7 +294,7 @@ class iunordered_set_index size_type cur_size = this->size(); size_type cur_count = this->bucket_count(); bucket_ptr old_p = this->bucket_pointer(); - + if(!this->size() && old_p != bucket_ptr(&this->init_bucket)){ this->rehash(bucket_traits(bucket_ptr(&this->init_bucket), 1)); destroy_buckets(this->alloc, old_p, cur_count); @@ -337,7 +341,7 @@ class iunordered_set_index //Strong guarantee: if something goes wrong //we should remove the insertion. // - //We can use the iterator because the hash function + //We can use the iterator because the hash function //can't throw and this means that "reserve" will //throw only because of the memory allocation: //the iterator has not been invalidated. @@ -349,7 +353,7 @@ class iunordered_set_index } }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Trait class to detect if an index is an intrusive //!index @@ -359,7 +363,7 @@ struct is_intrusive_index { static const bool value = true; }; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }} //namespace boost { namespace interprocess { diff --git a/boost/interprocess/indexes/map_index.hpp b/boost/interprocess/indexes/map_index.hpp index 1bfc7ce310..a744e9000e 100644 --- a/boost/interprocess/indexes/map_index.hpp +++ b/boost/interprocess/indexes/map_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_MAP_INDEX_HPP #define BOOST_INTERPROCESS_MAP_INDEX_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -55,12 +59,12 @@ class map_index //Derive class from map specialization : public ipcdetail::map_index_aux<MapConfig>::index_t { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef ipcdetail::map_index_aux<MapConfig> index_aux; typedef typename index_aux::index_t base_type; typedef typename MapConfig:: segment_manager_base segment_manager_base; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Takes a pointer to the @@ -80,7 +84,7 @@ class map_index { base_type::get_stored_allocator().deallocate_free_blocks(); } }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Trait class to detect if an index is a node //!index. This allows more efficient operations @@ -91,7 +95,7 @@ struct is_node_index { static const bool value = true; }; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }} //namespace boost { namespace interprocess { diff --git a/boost/interprocess/indexes/null_index.hpp b/boost/interprocess/indexes/null_index.hpp index a0353b101c..d0e026b896 100644 --- a/boost/interprocess/indexes/null_index.hpp +++ b/boost/interprocess/indexes/null_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -10,6 +10,10 @@ #ifndef BOOST_INTERPROCESS_NULL_INDEX_HPP #define BOOST_INTERPROCESS_NULL_INDEX_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -28,14 +32,14 @@ namespace interprocess { template <class MapConfig> class null_index { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef typename MapConfig:: segment_manager_base segment_manager_base; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: - typedef void * iterator; - typedef const void * const_iterator; + typedef int * iterator; + typedef const int * const_iterator; //!begin() is equal //!to end() diff --git a/boost/interprocess/indexes/unordered_map_index.hpp b/boost/interprocess/indexes/unordered_map_index.hpp index 7cf4b85e65..f40d970819 100644 --- a/boost/interprocess/indexes/unordered_map_index.hpp +++ b/boost/interprocess/indexes/unordered_map_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP #define BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -27,7 +31,7 @@ namespace boost { namespace interprocess { -///@cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Helper class to define typedefs from //!IndexTraits @@ -57,7 +61,7 @@ struct unordered_map_index_aux key_equal, allocator_type> index_t; }; -///@endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Index type based in unordered_map. Just derives from unordered_map and //!defines the interface needed by managed memory segments @@ -66,12 +70,12 @@ class unordered_map_index //Derive class from unordered_map specialization : public unordered_map_index_aux<MapConfig>::index_t { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef unordered_map_index_aux<MapConfig> index_aux; typedef typename index_aux::index_t base_type; typedef typename MapConfig::segment_manager_base segment_manager_base; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Takes a pointer to the @@ -93,7 +97,7 @@ class unordered_map_index { base_type::rehash(base_type::size()); } }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Trait class to detect if an index is a node //!index. This allows more efficient operations @@ -104,7 +108,7 @@ struct is_node_index { static const bool value = true; }; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }} //namespace boost { namespace interprocess { diff --git a/boost/interprocess/interprocess_fwd.hpp b/boost/interprocess/interprocess_fwd.hpp index 68fd89fb91..6c9675b401 100644 --- a/boost/interprocess/interprocess_fwd.hpp +++ b/boost/interprocess/interprocess_fwd.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,21 +11,118 @@ #ifndef BOOST_INTERPROCESS_FWD_HPP #define BOOST_INTERPROCESS_FWD_HPP -#if defined (_MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif +//! \file +//! This header file forward declares the basic interprocess types: +//! - boost::interprocess::offset_ptr; +//! - boost::interprocess::permissions; +//! - boost::interprocess::mapped_region; +//! - boost::interprocess::file_mapping; +//! - boost::interprocess::shared_memory_object; +//! - boost::interprocess::windows_shared_memory; +//! - boost::interprocess::xsi_shared_memory; +//! +//! The following synchronization mechanisms and locks: +//! - boost::interprocess::null_mutex; +//! - boost::interprocess::interprocess_mutex; +//! - boost::interprocess::interprocess_recursive_mutex; +//! - boost::interprocess::interprocess_semaphore; +//! - boost::interprocess::named_mutex; +//! - boost::interprocess::named_recursive_mutex; +//! - boost::interprocess::named_semaphore; +//! - boost::interprocess::interprocess_sharable_mutex; +//! - boost::interprocess::interprocess_condition; +//! - boost::interprocess::scoped_lock; +//! - boost::interprocess::sharable_lock; +//! - boost::interprocess::upgradable_lock; +//! +//! The following mutex families: +//! - boost::interprocess::mutex_family; +//! - boost::interprocess::null_mutex_family; +//! +//! The following allocators: +//! - boost::interprocess::allocator; +//! - boost::interprocess::node_allocator; +//! - boost::interprocess::private_node_allocator; +//! - boost::interprocess::cached_node_allocator; +//! - boost::interprocess::adaptive_pool; +//! - boost::interprocess::private_adaptive_pool; +//! - boost::interprocess::cached_adaptive_pool; +//! +//! The following allocation algorithms: +//! - boost::interprocess::simple_seq_fit; +//! - boost::interprocess::rbtree_best_fit; +//! +//! The following index types: +//! - boost::interprocess::flat_map_index; +//! - boost::interprocess::iset_index; +//! - boost::interprocess::iunordered_set_index; +//! - boost::interprocess::map_index; +//! - boost::interprocess::null_index; +//! - boost::interprocess::unordered_map_index; +//! +//! The following managed memory types: +//! - boost::interprocess::segment_manager; +//! - boost::interprocess::basic_managed_external_buffer +//! - boost::interprocess::managed_external_buffer +//! - boost::interprocess::wmanaged_external_buffer +//! - boost::interprocess::basic_managed_shared_memory +//! - boost::interprocess::managed_shared_memory +//! - boost::interprocess::wmanaged_shared_memory +//! - boost::interprocess::basic_managed_windows_shared_memory +//! - boost::interprocess::managed_windows_shared_memory +//! - boost::interprocess::wmanaged_windows_shared_memory +//! - boost::interprocess::basic_managed_xsi_shared_memory +//! - boost::interprocess::managed_xsi_shared_memory +//! - boost::interprocess::wmanaged_xsi_shared_memory +//! - boost::interprocess::fixed_managed_shared_memory +//! - boost::interprocess::wfixed_managed_shared_memory +//! - boost::interprocess::basic_managed_heap_memory +//! - boost::interprocess::managed_heap_memory +//! - boost::interprocess::wmanaged_heap_memory +//! - boost::interprocess::basic_managed_mapped_file +//! - boost::interprocess::managed_mapped_file +//! - boost::interprocess::wmanaged_mapped_file +//! +//! The following exception types: +//! - boost::interprocess::interprocess_exception +//! - boost::interprocess::lock_exception +//! - boost::interprocess::bad_alloc +//! +//! The following stream types: +//! - boost::interprocess::basic_bufferbuf +//! - boost::interprocess::basic_ibufferstream +//! - boost::interprocess::basic_obufferstream +//! - boost::interprocess::basic_bufferstream +//! - boost::interprocess::basic_vectorbuf +//! - boost::interprocess::basic_ivectorstream +//! - boost::interprocess::basic_ovectorstream +//! - boost::interprocess::basic_vectorstream +//! +//! The following smart pointer types: +//! - boost::interprocess::scoped_ptr +//! - boost::interprocess::intrusive_ptr +//! - boost::interprocess::shared_ptr +//! - boost::interprocess::weak_ptr +//! +//! The following interprocess communication types: +//! - boost::interprocess::message_queue_t; +//! - boost::interprocess::message_queue; + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #include <cstddef> ////////////////////////////////////////////////////////////////////////////// // Standard predeclarations ////////////////////////////////////////////////////////////////////////////// -/// @cond - namespace boost{ namespace intrusive{ }} @@ -41,8 +138,6 @@ namespace bi = boost::intrusive; #include <iosfwd> #include <string> -/// @endcond - namespace boost { namespace interprocess { ////////////////////////////////////////////////////////////////////////////// @@ -57,17 +152,20 @@ class permissions; class shared_memory_object; -#if defined (BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +#if defined (BOOST_INTERPROCESS_WINDOWS) class windows_shared_memory; #endif //#if defined (BOOST_INTERPROCESS_WINDOWS) +#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) +class xsi_shared_memory; +#endif //#if defined (BOOST_INTERPROCESS_WINDOWS) + ////////////////////////////////////////////////////////////////////////////// -// mapped file/mapped region/mapped_file +// file mapping / mapped region ////////////////////////////////////////////////////////////////////////////// class file_mapping; class mapped_region; -class mapped_file; ////////////////////////////////////////////////////////////////////////////// // Mutexes @@ -95,7 +193,6 @@ struct null_mutex_family; // Other synchronization classes ////////////////////////////////////////////////////////////////////////////// -class barrier; class interprocess_sharable_mutex; class interprocess_condition; @@ -231,7 +328,7 @@ wmanaged_shared_memory; // Windows shared memory managed memory classes ////////////////////////////////////////////////////////////////////////////// -#if defined (BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +#if defined (BOOST_INTERPROCESS_WINDOWS) template <class CharType ,class MemoryAlgorithm @@ -252,7 +349,7 @@ wmanaged_windows_shared_memory; #endif //#if defined (BOOST_INTERPROCESS_WINDOWS) -#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) template <class CharType ,class MemoryAlgorithm @@ -409,9 +506,7 @@ typedef message_queue_t<offset_ptr<void> > message_queue; }} //namespace boost { namespace interprocess { -////////////////////////////////////////////////////////////////////////////// -// CONTAINERS -////////////////////////////////////////////////////////////////////////////// +#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/ipc/message_queue.hpp b/boost/interprocess/ipc/message_queue.hpp index 67dd574f61..09290587d9 100644 --- a/boost/interprocess/ipc/message_queue.hpp +++ b/boost/interprocess/ipc/message_queue.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP #define BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -30,6 +34,7 @@ #include <boost/type_traits/make_unsigned.hpp> #include <boost/type_traits/alignment_of.hpp> #include <boost/intrusive/pointer_traits.hpp> +#include <boost/assert.hpp> #include <algorithm> //std::lower_bound #include <cstddef> //std::size_t #include <cstring> //memcpy @@ -42,17 +47,23 @@ namespace boost{ namespace interprocess{ +namespace ipcdetail +{ + template<class VoidPointer> + class msg_queue_initialization_func_t; +} + //!A class that allows sending messages //!between processes. template<class VoidPointer> class message_queue_t { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Blocking modes enum block_t { blocking, timed, non_blocking }; message_queue_t(); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: typedef VoidPointer void_pointer; @@ -99,7 +110,7 @@ class message_queue_t //!Sends a message stored in buffer "buffer" with size "buffer_size" in the //!message queue with priority "priority". If the message queue is full - //!the sender is blocked. Throws interprocess_error on error.*/ + //!the sender is blocked. Throws interprocess_error on error. void send (const void *buffer, size_type buffer_size, unsigned int priority); @@ -155,15 +166,18 @@ class message_queue_t //!Returns the number of messages currently stored. //!Never throws - size_type get_num_msg(); + size_type get_num_msg() const; //!Removes the message queue from the system. //!Returns false on error. Never throws static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef boost::posix_time::ptime ptime; + + friend class ipcdetail::msg_queue_initialization_func_t<VoidPointer>; + bool do_receive(block_t block, void *buffer, size_type buffer_size, size_type &recvd_size, unsigned int &priority, @@ -176,12 +190,12 @@ class message_queue_t //!Returns the needed memory size for the shared message queue. //!Never throws static size_type get_mem_size(size_type max_msg_size, size_type max_num_msg); - - ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem; - /// @endcond + typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t; + open_create_impl_t m_shmem; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail { @@ -227,9 +241,27 @@ class priority_functor //! //!-> offset_ptr<msg_hdr_t> index [max_num_msg] //! An array of pointers with size "max_num_msg" called index. Each pointer -//! points to a preallocated message. The elements of this array are +//! points to a preallocated message. Elements of this array are //! reordered in runtime in the following way: //! +//! IF BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is defined: +//! +//! When the current number of messages is "cur_num_msg", the array +//! is treated like a circular buffer. Starting from position "cur_first_msg" +//! "cur_num_msg" in a circular way, pointers point to inserted messages and the rest +//! point to free messages. Those "cur_num_msg" pointers are +//! ordered by the priority of the pointed message and by insertion order +//! if two messages have the same priority. So the next message to be +//! used in a "receive" is pointed by index [(cur_first_msg + cur_num_msg-1)%max_num_msg] +//! and the first free message ready to be used in a "send" operation is +//! [cur_first_msg] if circular buffer is extended from front, +//! [(cur_first_msg + cur_num_msg)%max_num_msg] otherwise. +//! +//! This transforms the index in a circular buffer with an embedded free +//! message queue. +//! +//! ELSE (BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is NOT defined): +//! //! When the current number of messages is "cur_num_msg", the first //! "cur_num_msg" pointers point to inserted messages and the rest //! point to free messages. The first "cur_num_msg" pointers are @@ -237,11 +269,12 @@ class priority_functor //! if two messages have the same priority. So the next message to be //! used in a "receive" is pointed by index [cur_num_msg-1] and the first free //! message ready to be used in a "send" operation is index [cur_num_msg]. -//! This transforms index in a fixed size priority queue with an embedded free +//! +//! This transforms the index in a fixed size priority queue with an embedded free //! message queue. //! //!-> struct message_t -//! { +//! { //! msg_hdr_t header; //! char[max_msg_size] data; //! } messages [max_num_msg]; @@ -252,7 +285,7 @@ class priority_functor template<class VoidPointer> class mq_hdr_t : public ipcdetail::priority_functor<VoidPointer> -{ +{ typedef VoidPointer void_pointer; typedef msg_hdr_t<void_pointer> msg_header; typedef typename boost::intrusive:: @@ -264,22 +297,24 @@ class mq_hdr_t typedef typename boost::intrusive:: pointer_traits<void_pointer>::template rebind_pointer<msg_hdr_ptr_t>::type msg_hdr_ptr_ptr_t; + typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t; public: //!Constructor. This object must be constructed in the beginning of the //!shared memory of the size returned by the function "get_mem_size". //!This constructor initializes the needed resources and creates - //!the internal structures like the priority index. This can throw.*/ + //!the internal structures like the priority index. This can throw. mq_hdr_t(size_type max_num_msg, size_type max_msg_size) : m_max_num_msg(max_num_msg), m_max_msg_size(max_msg_size), m_cur_num_msg(0) + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + ,m_cur_first_msg(0u) + ,m_blocked_senders(0u) + ,m_blocked_receivers(0u) + #endif { this->initialize_memory(); } - //!Returns the inserted message with top priority - msg_header * top_msg() - { return mp_index[m_cur_num_msg-1].get(); } - //!Returns true if the message queue is full bool is_full() const { return m_cur_num_msg == m_max_num_msg; } @@ -292,24 +327,195 @@ class mq_hdr_t void free_top_msg() { --m_cur_num_msg; } - //!Returns the first free msg of the free message queue - msg_header * free_msg() - { return mp_index[m_cur_num_msg].get(); } + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + + typedef msg_hdr_ptr_t *iterator; + + size_type end_pos() const + { + const size_type space_until_bufend = m_max_num_msg - m_cur_first_msg; + return space_until_bufend > m_cur_num_msg + ? m_cur_first_msg + m_cur_num_msg : m_cur_num_msg - space_until_bufend; + } + + //!Returns the inserted message with top priority + msg_header &top_msg() + { + size_type pos = this->end_pos(); + return *mp_index[pos ? --pos : m_max_num_msg - 1]; + } + + //!Returns the inserted message with bottom priority + msg_header &bottom_msg() + { return *mp_index[m_cur_first_msg]; } + + iterator inserted_ptr_begin() const + { return &mp_index[m_cur_first_msg]; } + + iterator inserted_ptr_end() const + { return &mp_index[this->end_pos()]; } + + iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor<VoidPointer> func) + { + iterator begin(this->inserted_ptr_begin()), end(this->inserted_ptr_end()); + if(end < begin){ + iterator idx_end = &mp_index[m_max_num_msg]; + iterator ret = std::lower_bound(begin, idx_end, value, func); + if(idx_end == ret){ + iterator idx_beg = &mp_index[0]; + ret = std::lower_bound(idx_beg, end, value, func); + //sanity check, these cases should not call lower_bound (optimized out) + BOOST_ASSERT(ret != end); + BOOST_ASSERT(ret != begin); + return ret; + } + else{ + return ret; + } + } + else{ + return std::lower_bound(begin, end, value, func); + } + } + + msg_header & insert_at(iterator where) + { + iterator it_inserted_ptr_end = this->inserted_ptr_end(); + iterator it_inserted_ptr_beg = this->inserted_ptr_begin(); + if(where == it_inserted_ptr_beg){ + //unsigned integer guarantees underflow + m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg; + --m_cur_first_msg; + ++m_cur_num_msg; + return *mp_index[m_cur_first_msg]; + } + else if(where == it_inserted_ptr_end){ + ++m_cur_num_msg; + return **it_inserted_ptr_end; + } + else{ + size_type pos = where - &mp_index[0]; + size_type circ_pos = pos >= m_cur_first_msg ? pos - m_cur_first_msg : pos + (m_max_num_msg - m_cur_first_msg); + //Check if it's more efficient to move back or move front + if(circ_pos < m_cur_num_msg/2){ + //The queue can't be full so m_cur_num_msg == 0 or m_cur_num_msg <= pos + //indicates two step insertion + if(!pos){ + pos = m_max_num_msg; + where = &mp_index[m_max_num_msg-1]; + } + else{ + --where; + } + const bool unique_segment = m_cur_first_msg && m_cur_first_msg <= pos; + const size_type first_segment_beg = unique_segment ? m_cur_first_msg : 1u; + const size_type first_segment_end = pos; + const size_type second_segment_beg = unique_segment || !m_cur_first_msg ? m_max_num_msg : m_cur_first_msg; + const size_type second_segment_end = m_max_num_msg; + const msg_hdr_ptr_t backup = *(&mp_index[0] + (unique_segment ? first_segment_beg : second_segment_beg) - 1); + + //First segment + if(!unique_segment){ + std::copy( &mp_index[0] + second_segment_beg + , &mp_index[0] + second_segment_end + , &mp_index[0] + second_segment_beg - 1); + mp_index[m_max_num_msg-1] = mp_index[0]; + } + std::copy( &mp_index[0] + first_segment_beg + , &mp_index[0] + first_segment_end + , &mp_index[0] + first_segment_beg - 1); + *where = backup; + m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg; + --m_cur_first_msg; + ++m_cur_num_msg; + return **where; + } + else{ + //The queue can't be full so end_pos < m_cur_first_msg + //indicates two step insertion + const size_type pos_end = this->end_pos(); + const bool unique_segment = pos < pos_end; + const size_type first_segment_beg = pos; + const size_type first_segment_end = unique_segment ? pos_end : m_max_num_msg-1; + const size_type second_segment_beg = 0u; + const size_type second_segment_end = unique_segment ? 0u : pos_end; + const msg_hdr_ptr_t backup = *it_inserted_ptr_end; + + //First segment + if(!unique_segment){ + std::copy_backward( &mp_index[0] + second_segment_beg + , &mp_index[0] + second_segment_end + , &mp_index[0] + second_segment_end + 1); + mp_index[0] = mp_index[m_max_num_msg-1]; + } + std::copy_backward( &mp_index[0] + first_segment_beg + , &mp_index[0] + first_segment_end + , &mp_index[0] + first_segment_end + 1); + *where = backup; + ++m_cur_num_msg; + return **where; + } + } + } + + #else //BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + + typedef msg_hdr_ptr_t *iterator; + + //!Returns the inserted message with top priority + msg_header &top_msg() + { return *mp_index[m_cur_num_msg-1]; } + + //!Returns the inserted message with bottom priority + msg_header &bottom_msg() + { return *mp_index[0]; } + + iterator inserted_ptr_begin() const + { return &mp_index[0]; } + + iterator inserted_ptr_end() const + { return &mp_index[m_cur_num_msg]; } + + iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor<VoidPointer> func) + { return std::lower_bound(this->inserted_ptr_begin(), this->inserted_ptr_end(), value, func); } + + msg_header & insert_at(iterator pos) + { + const msg_hdr_ptr_t backup = *inserted_ptr_end(); + std::copy_backward(pos, inserted_ptr_end(), inserted_ptr_end()+1); + *pos = backup; + ++m_cur_num_msg; + return **pos; + } + + #endif //BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX //!Inserts the first free message in the priority queue - void queue_free_msg() - { - //Get free msg - msg_hdr_ptr_t free = mp_index[m_cur_num_msg]; + msg_header & queue_free_msg(unsigned int priority) + { //Get priority queue's range - msg_hdr_ptr_t *it = &mp_index[0], *it_end = &mp_index[m_cur_num_msg]; - //Check where the free message should be placed - it = std::lower_bound(it, it_end, free, static_cast<priority_functor<VoidPointer>&>(*this)); - //Make room in that position - std::copy_backward(it, it_end, it_end+1); + iterator it (inserted_ptr_begin()), it_end(inserted_ptr_end()); + //Optimize for non-priority usage + if(m_cur_num_msg && priority > this->bottom_msg().priority){ + //Check for higher priority than all stored messages + if(priority > this->top_msg().priority){ + it = it_end; + } + else{ + //Since we don't now which free message we will pick + //build a dummy header for searches + msg_header dummy_hdr; + dummy_hdr.priority = priority; + + //Get free msg + msg_hdr_ptr_t dummy_ptr(&dummy_hdr); + + //Check where the free message should be placed + it = this->lower_bound(dummy_ptr, static_cast<priority_functor<VoidPointer>&>(*this)); + } + } //Insert the free message in the correct position - *it = free; - ++m_cur_num_msg; + return this->insert_at(it); } //!Returns the number of bytes needed to construct a message queue with @@ -319,13 +525,13 @@ class mq_hdr_t (size_type max_msg_size, size_type max_num_msg) { const size_type - msg_hdr_align = ::boost::alignment_of<msg_header>::value, - index_align = ::boost::alignment_of<msg_hdr_ptr_t>::value, + msg_hdr_align = ::boost::alignment_of<msg_header>::value, + index_align = ::boost::alignment_of<msg_hdr_ptr_t>::value, r_hdr_size = ipcdetail::ct_rounded_size<sizeof(mq_hdr_t), index_align>::value, - r_index_size = ipcdetail::get_rounded_size(sizeof(msg_hdr_ptr_t)*max_num_msg, msg_hdr_align), - r_max_msg_size = ipcdetail::get_rounded_size(max_msg_size, msg_hdr_align) + sizeof(msg_header); + r_index_size = ipcdetail::get_rounded_size<size_type>(max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align), + r_max_msg_size = ipcdetail::get_rounded_size<size_type>(max_msg_size, msg_hdr_align) + sizeof(msg_header); return r_hdr_size + r_index_size + (max_num_msg*r_max_msg_size) + - ipcdetail::managed_open_or_create_impl<shared_memory_object>::ManagedOpenOrCreateUserOffset; + open_create_impl_t::ManagedOpenOrCreateUserOffset; } //!Initializes the memory structures to preallocate messages and constructs the @@ -333,11 +539,11 @@ class mq_hdr_t void initialize_memory() { const size_type - msg_hdr_align = ::boost::alignment_of<msg_header>::value, - index_align = ::boost::alignment_of<msg_hdr_ptr_t>::value, + msg_hdr_align = ::boost::alignment_of<msg_header>::value, + index_align = ::boost::alignment_of<msg_hdr_ptr_t>::value, r_hdr_size = ipcdetail::ct_rounded_size<sizeof(mq_hdr_t), index_align>::value, - r_index_size = ipcdetail::get_rounded_size(sizeof(msg_hdr_ptr_t)*m_max_num_msg, msg_hdr_align), - r_max_msg_size = ipcdetail::get_rounded_size(m_max_msg_size, msg_hdr_align) + sizeof(msg_header); + r_index_size = ipcdetail::get_rounded_size<size_type>(m_max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align), + r_max_msg_size = ipcdetail::get_rounded_size<size_type>(m_max_msg_size, msg_hdr_align) + sizeof(msg_header); //Pointer to the index msg_hdr_ptr_t *index = reinterpret_cast<msg_hdr_ptr_t*> @@ -345,7 +551,7 @@ class mq_hdr_t //Pointer to the first message header msg_header *msg_hdr = reinterpret_cast<msg_header*> - (reinterpret_cast<char*>(this)+r_hdr_size+r_index_size); + (reinterpret_cast<char*>(this)+r_hdr_size+r_index_size); //Initialize the pointer to the index mp_index = index; @@ -373,13 +579,19 @@ class mq_hdr_t interprocess_condition m_cond_recv; //Condition block senders when the queue is full interprocess_condition m_cond_send; + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + //Current start offset in the circular index + size_type m_cur_first_msg; + size_type m_blocked_senders; + size_type m_blocked_receivers; + #endif }; //!This is the atomic functor to be executed when creating or opening //!shared memory. Never throws template<class VoidPointer> -class initialization_func_t +class msg_queue_initialization_func_t { public: typedef typename boost::intrusive:: @@ -388,7 +600,7 @@ class initialization_func_t typedef typename boost::intrusive::pointer_traits<char_ptr>::difference_type difference_type; typedef typename boost::make_unsigned<difference_type>::type size_type; - initialization_func_t(size_type maxmsg = 0, + msg_queue_initialization_func_t(size_type maxmsg = 0, size_type maxmsgsize = 0) : m_maxmsg (maxmsg), m_maxmsgsize(maxmsgsize) {} @@ -403,12 +615,19 @@ class initialization_func_t new (mptr) mq_hdr_t<VoidPointer>(m_maxmsg, m_maxmsgsize); } BOOST_CATCH(...){ - return false; + return false; } BOOST_CATCH_END } return true; } + + std::size_t get_min_size() const + { + return mq_hdr_t<VoidPointer>::get_mem_size(m_maxmsgsize, m_maxmsg) + - message_queue_t<VoidPointer>::open_create_impl_t::ManagedOpenOrCreateUserOffset; + } + const size_type m_maxmsg; const size_type m_maxmsgsize; }; @@ -425,7 +644,7 @@ inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPoin { return ipcdetail::mq_hdr_t<VoidPointer>::get_mem_size(max_msg_size, max_num_msg); } template<class VoidPointer> -inline message_queue_t<VoidPointer>::message_queue_t(create_only_t create_only, +inline message_queue_t<VoidPointer>::message_queue_t(create_only_t, const char *name, size_type max_num_msg, size_type max_msg_size, @@ -433,16 +652,16 @@ inline message_queue_t<VoidPointer>::message_queue_t(create_only_t create_only, //Create shared memory and execute functor atomically : m_shmem(create_only, name, - get_mem_size(max_msg_size, max_num_msg), + get_mem_size(max_msg_size, max_num_msg), read_write, static_cast<void*>(0), //Prepare initialization functor - ipcdetail::initialization_func_t<VoidPointer> (max_num_msg, max_msg_size), + ipcdetail::msg_queue_initialization_func_t<VoidPointer> (max_num_msg, max_msg_size), perm) {} template<class VoidPointer> -inline message_queue_t<VoidPointer>::message_queue_t(open_or_create_t open_or_create, +inline message_queue_t<VoidPointer>::message_queue_t(open_or_create_t, const char *name, size_type max_num_msg, size_type max_msg_size, @@ -454,20 +673,19 @@ inline message_queue_t<VoidPointer>::message_queue_t(open_or_create_t open_or_cr read_write, static_cast<void*>(0), //Prepare initialization functor - ipcdetail::initialization_func_t<VoidPointer> (max_num_msg, max_msg_size), + ipcdetail::msg_queue_initialization_func_t<VoidPointer> (max_num_msg, max_msg_size), perm) {} template<class VoidPointer> -inline message_queue_t<VoidPointer>::message_queue_t(open_only_t open_only, - const char *name) +inline message_queue_t<VoidPointer>::message_queue_t(open_only_t, const char *name) //Create shared memory and execute functor atomically : m_shmem(open_only, name, read_write, static_cast<void*>(0), //Prepare initialization functor - ipcdetail::initialization_func_t<VoidPointer> ()) + ipcdetail::msg_queue_initialization_func_t<VoidPointer> ()) {} template<class VoidPointer> @@ -503,63 +721,93 @@ inline bool message_queue_t<VoidPointer>::do_send(block_t block, throw interprocess_exception(size_error); } + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + bool notify_blocked_receivers = false; + #endif //--------------------------------------------- scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex); //--------------------------------------------- { //If the queue is full execute blocking logic if (p_hdr->is_full()) { - - switch(block){ - case non_blocking : - return false; - break; - - case blocking : - do{ - p_hdr->m_cond_send.wait(lock); - } - while (p_hdr->is_full()); - break; - - case timed : - do{ - if(!p_hdr->m_cond_send.timed_wait(lock, abs_time)){ - if(p_hdr->is_full()) - return false; - break; + BOOST_TRY{ + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + ++p_hdr->m_blocked_senders; + #endif + switch(block){ + case non_blocking : + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + --p_hdr->m_blocked_senders; + #endif + return false; + break; + + case blocking : + do{ + p_hdr->m_cond_send.wait(lock); + } + while (p_hdr->is_full()); + break; + + case timed : + do{ + if(!p_hdr->m_cond_send.timed_wait(lock, abs_time)){ + if(p_hdr->is_full()){ + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + --p_hdr->m_blocked_senders; + #endif + return false; + } + break; + } } - } - while (p_hdr->is_full()); - break; - default: - break; + while (p_hdr->is_full()); + break; + default: + break; + } + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + --p_hdr->m_blocked_senders; + #endif } + BOOST_CATCH(...){ + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + --p_hdr->m_blocked_senders; + #endif + BOOST_RETHROW; + } + BOOST_CATCH_END } - - //Get the first free message from free message queue - ipcdetail::msg_hdr_t<VoidPointer> *free_msg = p_hdr->free_msg(); - if (free_msg == 0) { - throw interprocess_exception("boost::interprocess::message_queue corrupted"); - } + + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + notify_blocked_receivers = 0 != p_hdr->m_blocked_receivers; + #endif + //Insert the first free message in the priority queue + ipcdetail::msg_hdr_t<VoidPointer> &free_msg_hdr = p_hdr->queue_free_msg(priority); + + //Sanity check, free msgs are always cleaned when received + BOOST_ASSERT(free_msg_hdr.priority == 0); + BOOST_ASSERT(free_msg_hdr.len == 0); //Copy control data to the free message - free_msg->priority = priority; - free_msg->len = buffer_size; + free_msg_hdr.priority = priority; + free_msg_hdr.len = buffer_size; //Copy user buffer to the message - std::memcpy(free_msg->data(), buffer, buffer_size); - -// bool was_empty = p_hdr->is_empty(); - //Insert the first free message in the priority queue - p_hdr->queue_free_msg(); - - //If this message changes the queue empty state, notify it to receivers -// if (was_empty){ - p_hdr->m_cond_recv.notify_one(); -// } + std::memcpy(free_msg_hdr.data(), buffer, buffer_size); } // Lock end + //Notify outside lock to avoid contention. This might produce some + //spurious wakeups, but it's usually far better than notifying inside. + //If this message changes the queue empty state, notify it to receivers + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + if (notify_blocked_receivers){ + p_hdr->m_cond_recv.notify_one(); + } + #else + p_hdr->m_cond_recv.notify_one(); + #endif + return true; } @@ -600,86 +848,118 @@ inline bool throw interprocess_exception(size_error); } + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + bool notify_blocked_senders = false; + #endif //--------------------------------------------- scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex); //--------------------------------------------- { //If there are no messages execute blocking logic if (p_hdr->is_empty()) { - switch(block){ - case non_blocking : - return false; - break; - - case blocking : - do{ - p_hdr->m_cond_recv.wait(lock); - } - while (p_hdr->is_empty()); - break; - - case timed : - do{ - if(!p_hdr->m_cond_recv.timed_wait(lock, abs_time)){ - if(p_hdr->is_empty()) - return false; - break; + BOOST_TRY{ + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + ++p_hdr->m_blocked_receivers; + #endif + switch(block){ + case non_blocking : + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + --p_hdr->m_blocked_receivers; + #endif + return false; + break; + + case blocking : + do{ + p_hdr->m_cond_recv.wait(lock); } - } - while (p_hdr->is_empty()); - break; - - //Paranoia check - default: - break; + while (p_hdr->is_empty()); + break; + + case timed : + do{ + if(!p_hdr->m_cond_recv.timed_wait(lock, abs_time)){ + if(p_hdr->is_empty()){ + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + --p_hdr->m_blocked_receivers; + #endif + return false; + } + break; + } + } + while (p_hdr->is_empty()); + break; + + //Paranoia check + default: + break; + } + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + --p_hdr->m_blocked_receivers; + #endif + } + BOOST_CATCH(...){ + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + --p_hdr->m_blocked_receivers; + #endif + BOOST_RETHROW; } + BOOST_CATCH_END } - //Thre is at least message ready to pick, get the top one - ipcdetail::msg_hdr_t<VoidPointer> *top_msg = p_hdr->top_msg(); + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + notify_blocked_senders = 0 != p_hdr->m_blocked_senders; + #endif - //Paranoia check - if (top_msg == 0) { - throw interprocess_exception("boost::interprocess::message_queue corrupted"); - } + //There is at least one message ready to pick, get the top one + ipcdetail::msg_hdr_t<VoidPointer> &top_msg = p_hdr->top_msg(); //Get data from the message - recvd_size = top_msg->len; - priority = top_msg->priority; + recvd_size = top_msg.len; + priority = top_msg.priority; - //Copy data to receiver's bufers - std::memcpy(buffer, top_msg->data(), recvd_size); + //Some cleanup to ease debugging + top_msg.len = 0; + top_msg.priority = 0; -// bool was_full = p_hdr->is_full(); + //Copy data to receiver's bufers + std::memcpy(buffer, top_msg.data(), recvd_size); //Free top message and put it in the free message list p_hdr->free_top_msg(); - - //If this reception changes the queue full state, notify senders -// if (was_full){ - p_hdr->m_cond_send.notify_one(); -// } } //Lock end + //Notify outside lock to avoid contention. This might produce some + //spurious wakeups, but it's usually far better than notifying inside. + //If this reception changes the queue full state, notify senders + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + if (notify_blocked_senders){ + p_hdr->m_cond_send.notify_one(); + } + #else + p_hdr->m_cond_send.notify_one(); + #endif + return true; } template<class VoidPointer> inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_max_msg() const -{ +{ ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address()); return p_hdr ? p_hdr->m_max_num_msg : 0; } template<class VoidPointer> inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_max_msg_size() const -{ +{ ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address()); - return p_hdr ? p_hdr->m_max_msg_size : 0; + return p_hdr ? p_hdr->m_max_msg_size : 0; } template<class VoidPointer> -inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_num_msg() -{ +inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_num_msg() const +{ ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address()); if(p_hdr){ //--------------------------------------------- @@ -688,14 +968,20 @@ inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPoin return p_hdr->m_cur_num_msg; } - return 0; + return 0; } template<class VoidPointer> inline bool message_queue_t<VoidPointer>::remove(const char *name) { return shared_memory_object::remove(name); } -/// @endcond +#else + +//!Typedef for a default message queue +//!to be used between processes +typedef message_queue_t<offset_ptr<void> > message_queue; + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }} //namespace boost{ namespace interprocess{ diff --git a/boost/interprocess/managed_external_buffer.hpp b/boost/interprocess/managed_external_buffer.hpp index e268e57601..aa0c8c9d19 100644 --- a/boost/interprocess/managed_external_buffer.hpp +++ b/boost/interprocess/managed_external_buffer.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP #define BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -19,11 +19,11 @@ #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/detail/managed_memory_impl.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/assert.hpp> //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> +#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> #include <boost/interprocess/sync/mutex_family.hpp> #include <boost/interprocess/indexes/iset_index.hpp> @@ -45,12 +45,12 @@ template class basic_managed_external_buffer : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType> { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType> base_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_external_buffer) - /// @endcond - + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: typedef typename base_t::size_type size_type; @@ -104,6 +104,26 @@ class basic_managed_external_buffer { base_t::swap(other); } }; +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_external_buffer +//!of narrow characters +typedef basic_managed_external_buffer + <char + ,rbtree_best_fit<null_mutex_family> + ,iset_index> +managed_external_buffer; + +//!Typedef for a default basic_managed_external_buffer +//!of wide characters +typedef basic_managed_external_buffer + <wchar_t + ,rbtree_best_fit<null_mutex_family> + ,iset_index> +wmanaged_external_buffer; + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/managed_heap_memory.hpp b/boost/interprocess/managed_heap_memory.hpp index 87107855f2..77ba56d75a 100644 --- a/boost/interprocess/managed_heap_memory.hpp +++ b/boost/interprocess/managed_heap_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,20 +11,20 @@ #ifndef BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP #define BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/creation_tags.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <vector> #include <boost/interprocess/detail/managed_memory_impl.hpp> #include <boost/detail/no_exceptions_support.hpp> //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> +#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> #include <boost/interprocess/sync/mutex_family.hpp> #include <boost/interprocess/indexes/iset_index.hpp> @@ -46,13 +46,13 @@ template class basic_managed_heap_memory : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType> { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType> base_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_heap_memory) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //functions typedef typename base_t::size_type size_type; @@ -99,7 +99,7 @@ class basic_managed_heap_memory //!have some extra bytes to allocate new objects. If returns //!false, the heap allocation has failed. bool grow(size_type extra_bytes) - { + { //If memory is reallocated, data will //be automatically copied BOOST_TRY{ @@ -125,19 +125,38 @@ class basic_managed_heap_memory m_heapmem.swap(other.m_heapmem); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //!Frees resources. Never throws. void priv_close() - { + { base_t::destroy_impl(); std::vector<char>().swap(m_heapmem); } std::vector<char> m_heapmem; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_heap_memory +//!of narrow characters +typedef basic_managed_heap_memory + <char + ,rbtree_best_fit<null_mutex_family> + ,iset_index> +managed_heap_memory; + +//!Typedef for a default basic_managed_heap_memory +//!of wide characters +typedef basic_managed_heap_memory + <wchar_t + ,rbtree_best_fit<null_mutex_family> + ,iset_index> +wmanaged_heap_memory; + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/managed_mapped_file.hpp b/boost/interprocess/managed_mapped_file.hpp index 5a351adfa5..ee74c9f165 100644 --- a/boost/interprocess/managed_mapped_file.hpp +++ b/boost/interprocess/managed_mapped_file.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP #define BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -21,17 +21,27 @@ #include <boost/interprocess/detail/managed_memory_impl.hpp> #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/detail/file_wrapper.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/file_mapping.hpp> #include <boost/interprocess/permissions.hpp> //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> +#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> #include <boost/interprocess/sync/mutex_family.hpp> #include <boost/interprocess/indexes/iset_index.hpp> namespace boost { namespace interprocess { +namespace ipcdetail { + +template<class AllocationAlgorithm> +struct mfile_open_or_create +{ + typedef ipcdetail::managed_open_or_create_impl + < file_wrapper, AllocationAlgorithm::Alignment, true, false> type; +}; + +} //namespace ipcdetail { //!A basic mapped file named object creation class. Initializes the //!mapped file. Inherits all basic functionality from @@ -43,27 +53,22 @@ template template<class IndexConfig> class IndexType > class basic_managed_mapped_file + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType - ,ipcdetail::managed_open_or_create_impl< ipcdetail::file_wrapper - , AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset - > + ,ipcdetail::mfile_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) public: typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType, - ipcdetail::managed_open_or_create_impl - <ipcdetail::file_wrapper, AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset - > base_t; + ipcdetail::mfile_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> base_t; typedef ipcdetail::file_wrapper device_type; - typedef typename base_t::size_type size_type; private: - typedef ipcdetail::create_open_func<base_t> create_open_func_t; - typedef ipcdetail::managed_open_or_create_impl< ipcdetail::file_wrapper - , AllocationAlgorithm::Alignment> managed_open_or_create_type; + typedef ipcdetail::create_open_func<base_t> create_open_func_t; basic_managed_mapped_file *get_this_pointer() { return this; } @@ -71,10 +76,14 @@ class basic_managed_mapped_file private: typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_mapped_file) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //functions + //!Unsigned integral type enough to represent + //!the size of a basic_managed_mapped_file. + typedef typename BOOST_INTERPROCESS_IMPDEF(base_t::size_type) size_type; + //!Creates mapped file and creates and places the segment manager. //!This can throw. basic_managed_mapped_file() @@ -82,7 +91,7 @@ class basic_managed_mapped_file //!Creates mapped file and creates and places the segment manager. //!This can throw. - basic_managed_mapped_file(create_only_t create_only, const char *name, + basic_managed_mapped_file(create_only_t, const char *name, size_type size, const void *addr = 0, const permissions &perm = permissions()) : m_mfile(create_only, name, size, read_write, addr, create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) @@ -92,7 +101,7 @@ class basic_managed_mapped_file //!segment was not created. If segment was created it connects to the //!segment. //!This can throw. - basic_managed_mapped_file (open_or_create_t open_or_create, + basic_managed_mapped_file (open_or_create_t, const char *name, size_type size, const void *addr = 0, const permissions &perm = permissions()) : m_mfile(open_or_create, name, size, read_write, addr, @@ -102,7 +111,7 @@ class basic_managed_mapped_file //!Connects to a created mapped file and its segment manager. //!This can throw. - basic_managed_mapped_file (open_only_t open_only, const char* name, + basic_managed_mapped_file (open_only_t, const char* name, const void *addr = 0) : m_mfile(open_only, name, read_write, addr, create_open_func_t(get_this_pointer(), @@ -188,7 +197,7 @@ class basic_managed_mapped_file <basic_managed_mapped_file>(filename); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Tries to find a previous named allocation address. Returns a memory //!buffer and the object count. If not found returned pointer is 0. @@ -205,10 +214,30 @@ class basic_managed_mapped_file } private: - managed_open_or_create_type m_mfile; - /// @endcond + typename ipcdetail::mfile_open_or_create<AllocationAlgorithm>::type m_mfile; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_mapped_file +//!of narrow characters +typedef basic_managed_mapped_file + <char + ,rbtree_best_fit<mutex_family> + ,iset_index> +managed_mapped_file; + +//!Typedef for a default basic_managed_mapped_file +//!of wide characters +typedef basic_managed_mapped_file + <wchar_t + ,rbtree_best_fit<mutex_family> + ,iset_index> +wmanaged_mapped_file; + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/managed_shared_memory.hpp b/boost/interprocess/managed_shared_memory.hpp index 0f74c1a0b9..b58ca51dfc 100644 --- a/boost/interprocess/managed_shared_memory.hpp +++ b/boost/interprocess/managed_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP #define BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -25,13 +25,23 @@ #include <boost/interprocess/permissions.hpp> //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> +#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> #include <boost/interprocess/sync/mutex_family.hpp> namespace boost { - namespace interprocess { +namespace ipcdetail { + +template<class AllocationAlgorithm> +struct shmem_open_or_create +{ + typedef ipcdetail::managed_open_or_create_impl + < shared_memory_object, AllocationAlgorithm::Alignment, true, false> type; +}; + +} //namespace ipcdetail { + //!A basic shared memory named object creation class. Initializes the //!shared memory segment. Inherits all basic functionality from //!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/ @@ -44,18 +54,14 @@ template class basic_managed_shared_memory : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType - ,ipcdetail::managed_open_or_create_impl<shared_memory_object - , AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset> - , private ipcdetail::managed_open_or_create_impl<shared_memory_object - , AllocationAlgorithm::Alignment> + ,ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> + , private ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType, - ipcdetail::managed_open_or_create_impl - < shared_memory_object, AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset> base_t; - typedef ipcdetail::managed_open_or_create_impl - <shared_memory_object, AllocationAlgorithm::Alignment> base2_t; + ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> base_t; + typedef typename ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type base2_t; typedef ipcdetail::create_open_func<base_t> create_open_func_t; @@ -69,7 +75,7 @@ class basic_managed_shared_memory private: typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_shared_memory) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //functions @@ -89,7 +95,7 @@ class basic_managed_shared_memory //!Creates shared memory and creates and places the segment manager. //!This can throw. - basic_managed_shared_memory(create_only_t create_only, const char *name, + basic_managed_shared_memory(create_only_t, const char *name, size_type size, const void *addr = 0, const permissions& perm = permissions()) : base_t() , base2_t(create_only, name, size, read_write, addr, @@ -100,7 +106,7 @@ class basic_managed_shared_memory //!segment was not created. If segment was created it connects to the //!segment. //!This can throw. - basic_managed_shared_memory (open_or_create_t open_or_create, + basic_managed_shared_memory (open_or_create_t, const char *name, size_type size, const void *addr = 0, const permissions& perm = permissions()) : base_t() @@ -133,7 +139,7 @@ class basic_managed_shared_memory //!Connects to a created shared memory and its segment manager. //!This can throw. - basic_managed_shared_memory (open_only_t open_only, const char* name, + basic_managed_shared_memory (open_only_t, const char* name, const void *addr = 0) : base_t() , base2_t(open_only, name, read_write, addr, @@ -187,7 +193,7 @@ class basic_managed_shared_memory return base_t::template shrink_to_fit <basic_managed_shared_memory>(shmname); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Tries to find a previous named allocation address. Returns a memory //!buffer and the object count. If not found returned pointer is 0. @@ -203,9 +209,46 @@ class basic_managed_shared_memory } } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_shared_memory +//!of narrow characters +typedef basic_managed_shared_memory + <char + ,rbtree_best_fit<mutex_family> + ,iset_index> +managed_shared_memory; + +//!Typedef for a default basic_managed_shared_memory +//!of wide characters +typedef basic_managed_shared_memory + <wchar_t + ,rbtree_best_fit<mutex_family> + ,iset_index> +wmanaged_shared_memory; + +//!Typedef for a default basic_managed_shared_memory +//!of narrow characters to be placed in a fixed address +typedef basic_managed_shared_memory + <char + ,rbtree_best_fit<mutex_family, void*> + ,iset_index> +fixed_managed_shared_memory; + +//!Typedef for a default basic_managed_shared_memory +//!of narrow characters to be placed in a fixed address +typedef basic_managed_shared_memory + <wchar_t + ,rbtree_best_fit<mutex_family, void*> + ,iset_index> +wfixed_managed_shared_memory; + + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/managed_windows_shared_memory.hpp b/boost/interprocess/managed_windows_shared_memory.hpp index 414007a614..2298c799ba 100644 --- a/boost/interprocess/managed_windows_shared_memory.hpp +++ b/boost/interprocess/managed_windows_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP #define BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -22,16 +22,27 @@ #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/windows_shared_memory.hpp> #include <boost/interprocess/permissions.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> +#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> #include <boost/interprocess/sync/mutex_family.hpp> #include <boost/interprocess/indexes/iset_index.hpp> namespace boost { namespace interprocess { +namespace ipcdetail { + +template<class AllocationAlgorithm> +struct wshmem_open_or_create +{ + typedef ipcdetail::managed_open_or_create_impl + < windows_shared_memory, AllocationAlgorithm::Alignment, false, false> type; +}; + +} //namespace ipcdetail { + //!A basic managed windows shared memory creation class. Initializes the //!shared memory segment. Inherits all basic functionality from //!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType> @@ -52,18 +63,13 @@ template class basic_managed_windows_shared_memory : public ipcdetail::basic_managed_memory_impl < CharType, AllocationAlgorithm, IndexType - , ipcdetail::managed_open_or_create_impl - < windows_shared_memory - , AllocationAlgorithm::Alignment - , false>::ManagedOpenOrCreateUserOffset - > + , ipcdetail::wshmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType, - ipcdetail::managed_open_or_create_impl - <windows_shared_memory, AllocationAlgorithm::Alignment, false>::ManagedOpenOrCreateUserOffset> base_t; + ipcdetail::wshmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> base_t; typedef ipcdetail::create_open_func<base_t> create_open_func_t; basic_managed_windows_shared_memory *get_this_pointer() @@ -72,7 +78,7 @@ class basic_managed_windows_shared_memory private: typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_windows_shared_memory) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //functions typedef typename base_t::size_type size_type; @@ -85,7 +91,7 @@ class basic_managed_windows_shared_memory //!Creates shared memory and creates and places the segment manager. //!This can throw. basic_managed_windows_shared_memory - (create_only_t create_only, const char *name, + (create_only_t, const char *name, size_type size, const void *addr = 0, const permissions &perm = permissions()) : m_wshm(create_only, name, size, read_write, addr, create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) @@ -96,7 +102,7 @@ class basic_managed_windows_shared_memory //!segment. //!This can throw. basic_managed_windows_shared_memory - (open_or_create_t open_or_create, + (open_or_create_t, const char *name, size_type size, const void *addr = 0, const permissions &perm = permissions()) @@ -108,7 +114,7 @@ class basic_managed_windows_shared_memory //!Connects to a created shared memory and its segment manager. //!This can throw. basic_managed_windows_shared_memory - (open_only_t open_only, const char* name, const void *addr = 0) + (open_only_t, const char* name, const void *addr = 0) : m_wshm(open_only, name, read_write, addr, create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) @@ -164,7 +170,7 @@ class basic_managed_windows_shared_memory m_wshm.swap(other.m_wshm); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Tries to find a previous named allocation address. Returns a memory //!buffer and the object count. If not found returned pointer is 0. @@ -181,11 +187,31 @@ class basic_managed_windows_shared_memory } private: - ipcdetail::managed_open_or_create_impl< windows_shared_memory - , AllocationAlgorithm::Alignment, false> m_wshm; - /// @endcond + typename ipcdetail::wshmem_open_or_create<AllocationAlgorithm>::type m_wshm; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_windows_shared_memory +//!of narrow characters +typedef basic_managed_windows_shared_memory + <char + ,rbtree_best_fit<mutex_family> + ,iset_index> +managed_windows_shared_memory; + +//!Typedef for a default basic_managed_windows_shared_memory +//!of wide characters +typedef basic_managed_windows_shared_memory + <wchar_t + ,rbtree_best_fit<mutex_family> + ,iset_index> +wmanaged_windows_shared_memory; + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/managed_xsi_shared_memory.hpp b/boost/interprocess/managed_xsi_shared_memory.hpp index dc909f6824..f7a4b35c35 100644 --- a/boost/interprocess/managed_xsi_shared_memory.hpp +++ b/boost/interprocess/managed_xsi_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP #define BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -28,7 +28,7 @@ #include <boost/interprocess/creation_tags.hpp> //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> +#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> #include <boost/interprocess/sync/mutex_family.hpp> #include <boost/interprocess/indexes/iset_index.hpp> @@ -36,9 +36,20 @@ namespace boost { namespace interprocess { +namespace ipcdetail { + +template<class AllocationAlgorithm> +struct xsishmem_open_or_create +{ + typedef ipcdetail::managed_open_or_create_impl //!FileBased, StoreDevice + < xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment, false, true> type; +}; + +} //namespace ipcdetail { + //!A basic X/Open System Interface (XSI) shared memory named object creation class. Initializes the //!shared memory segment. Inherits all basic functionality from -//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/ +//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType> template < class CharType, @@ -48,19 +59,15 @@ template class basic_managed_xsi_shared_memory : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType - ,ipcdetail::managed_open_or_create_impl - < xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment - , false, true>::ManagedOpenOrCreateUserOffset> - , private ipcdetail::managed_open_or_create_impl - <xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment, false, true> + ,ipcdetail::xsishmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> + , private ipcdetail::xsishmem_open_or_create<AllocationAlgorithm>::type { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) public: typedef xsi_shared_memory_file_wrapper device_type; public: - typedef ipcdetail::managed_open_or_create_impl - <xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment, false, true> base2_t; + typedef typename ipcdetail::xsishmem_open_or_create<AllocationAlgorithm>::type base2_t; typedef ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType, base2_t::ManagedOpenOrCreateUserOffset> base_t; @@ -73,7 +80,7 @@ class basic_managed_xsi_shared_memory private: typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_xsi_shared_memory) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //functions typedef typename base_t::size_type size_type; @@ -94,7 +101,7 @@ class basic_managed_xsi_shared_memory //!Creates shared memory and creates and places the segment manager. //!This can throw. - basic_managed_xsi_shared_memory(create_only_t create_only, const xsi_key &key, + basic_managed_xsi_shared_memory(create_only_t, const xsi_key &key, std::size_t size, const void *addr = 0, const permissions& perm = permissions()) : base_t() , base2_t(create_only, key, size, read_write, addr, @@ -105,7 +112,7 @@ class basic_managed_xsi_shared_memory //!segment was not created. If segment was created it connects to the //!segment. //!This can throw. - basic_managed_xsi_shared_memory (open_or_create_t open_or_create, + basic_managed_xsi_shared_memory (open_or_create_t, const xsi_key &key, std::size_t size, const void *addr = 0, const permissions& perm = permissions()) : base_t() @@ -127,7 +134,7 @@ class basic_managed_xsi_shared_memory //!Connects to a created shared memory and its segment manager. //!This can throw. - basic_managed_xsi_shared_memory (open_only_t open_only, const xsi_key &key, + basic_managed_xsi_shared_memory (open_only_t, const xsi_key &key, const void *addr = 0) : base_t() , base2_t(open_only, key, read_write, addr, @@ -170,7 +177,7 @@ class basic_managed_xsi_shared_memory int get_shmid() const { return base2_t::get_device().get_shmid(); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Tries to find a previous named allocation address. Returns a memory //!buffer and the object count. If not found returned pointer is 0. @@ -186,9 +193,29 @@ class basic_managed_xsi_shared_memory } } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_xsi_shared_memory +//!of narrow characters +typedef basic_managed_xsi_shared_memory + <char + ,rbtree_best_fit<mutex_family> + ,iset_index> +managed_xsi_shared_memory; + +//!Typedef for a default basic_managed_xsi_shared_memory +//!of wide characters +typedef basic_managed_xsi_shared_memory + <wchar_t + ,rbtree_best_fit<mutex_family> + ,iset_index> +wmanaged_xsi_shared_memory; + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/mapped_region.hpp b/boost/interprocess/mapped_region.hpp index 522c1e403a..24e55263ea 100644 --- a/boost/interprocess/mapped_region.hpp +++ b/boost/interprocess/mapped_region.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,16 +11,33 @@ #ifndef BOOST_INTERPROCESS_MAPPED_REGION_HPP #define BOOST_INTERPROCESS_MAPPED_REGION_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/interprocess_fwd.hpp> #include <boost/interprocess/exceptions.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/utilities.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> #include <string> #include <boost/cstdint.hpp> +#include <boost/assert.hpp> +//Some Unixes use caddr_t instead of void * in madvise +// SunOS Tru64 HP-UX AIX +#if defined(sun) || defined(__sun) || defined(__osf__) || defined(__osf) || defined(_hpux) || defined(hpux) || defined(_AIX) +#define BOOST_INTERPROCESS_MADVISE_USES_CADDR_T +#include <sys/types.h> +#endif + +//A lot of UNIXes have destructive semantics for MADV_DONTNEED, so +//we need to be careful to allow it. +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) +#define BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS +#endif #if defined (BOOST_INTERPROCESS_WINDOWS) # include <boost/interprocess/detail/win32_api.hpp> @@ -40,7 +57,7 @@ # error Unknown platform # endif -#endif //#if (defined BOOST_INTERPROCESS_WINDOWS) +#endif //#if defined (BOOST_INTERPROCESS_WINDOWS) //!\file //!Describes mapped region class @@ -48,11 +65,18 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +//Solaris declares madvise only in some configurations but defines MADV_XXX, a bit confusing. +//Predeclare it here to avoid any compilation error +#if (defined(sun) || defined(__sun)) && defined(MADV_NORMAL) +extern "C" int madvise(caddr_t, size_t, int); +#endif + namespace ipcdetail{ class interprocess_tester; } namespace ipcdetail{ class raw_mapped_region_creator; } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!The mapped_region class represents a portion or region created from a //!memory_mappable object. @@ -62,10 +86,10 @@ namespace ipcdetail{ class raw_mapped_region_creator; } //!the region specified by the user. class mapped_region { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable BOOST_MOVABLE_BUT_NOT_COPYABLE(mapped_region) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: @@ -76,6 +100,22 @@ class mapped_region //!If an address is specified, both the offset and the address must be //!multiples of the page size. //! + //!The map is created using "default_map_options". This flag is OS + //!dependant and it should not be changed unless the user needs to + //!specify special options. + //! + //!In Windows systems "map_options" is a DWORD value passed as + //!"dwDesiredAccess" to "MapViewOfFileEx". If "default_map_options" is passed + //!it's initialized to zero. "map_options" is XORed with FILE_MAP_[COPY|READ|WRITE]. + //! + //!In UNIX systems and POSIX mappings "map_options" is an int value passed as "flags" + //!to "mmap". If "default_map_options" is specified it's initialized to MAP_NOSYNC + //!if that option exists and to zero otherwise. "map_options" XORed with MAP_PRIVATE or MAP_SHARED. + //! + //!In UNIX systems and XSI mappings "map_options" is an int value passed as "shmflg" + //!to "shmat". If "default_map_options" is specified it's initialized to zero. + //!"map_options" is XORed with SHM_RDONLY if needed. + //! //!The OS could allocate more pages than size/page_size(), but get_address() //!will always return the address passed in this function (if not null) and //!get_size() will return the specified size. @@ -84,7 +124,8 @@ class mapped_region ,mode_t mode ,offset_t offset = 0 ,std::size_t size = 0 - ,const void *address = 0); + ,const void *address = 0 + ,map_options_t map_options = default_map_options); //!Default constructor. Address will be 0 (nullptr). //!Size will be 0. @@ -117,6 +158,10 @@ class mapped_region return *this; } + //!Swaps the mapped_region with another + //!mapped region + void swap(mapped_region &other); + //!Returns the size of the mapping. Never throws. std::size_t get_size() const; @@ -135,16 +180,48 @@ class mapped_region //!Never throws. Returns false if operation could not be performed. bool flush(std::size_t mapping_offset = 0, std::size_t numbytes = 0, bool async = true); - //!Swaps the mapped_region with another - //!mapped region - void swap(mapped_region &other); + //!Shrinks current mapped region. If after shrinking there is no longer need for a previously + //!mapped memory page, accessing that page can trigger a segmentation fault. + //!Depending on the OS, this operation might fail (XSI shared memory), it can decommit storage + //!and free a portion of the virtual address space (e.g.POSIX) or this + //!function can release some physical memory wihout freeing any virtual address space(Windows). + //!Returns true on success. Never throws. + bool shrink_by(std::size_t bytes, bool from_back = true); + + //!This enum specifies region usage behaviors that an application can specify + //!to the mapped region implementation. + enum advice_types{ + //!Specifies that the application has no advice to give on its behavior with respect to + //!the region. It is the default characteristic if no advice is given for a range of memory. + advice_normal, + //!Specifies that the application expects to access the region sequentially from + //!lower addresses to higher addresses. The implementation can lower the priority of + //!preceding pages within the region once a page have been accessed. + advice_sequential, + //!Specifies that the application expects to access the region in a random order, + //!and prefetching is likely not advantageous. + advice_random, + //!Specifies that the application expects to access the region in the near future. + //!The implementation can prefetch pages of the region. + advice_willneed, + //!Specifies that the application expects that it will not access the region in the near future. + //!The implementation can unload pages within the range to save system resources. + advice_dontneed + }; + + //!Advises the implementation on the expected behavior of the application with respect to the data + //!in the region. The implementation may use this information to optimize handling of the region data. + //!This function has no effect on the semantics of access to memory in the region, although it may affect + //!the performance of access. + //!If the advise type is not known to the implementation, the function returns false. True otherwise. + bool advise(advice_types advise); //!Returns the size of the page. This size is the minimum memory that //!will be used by the system when mapping a memory mappable source and //!will restrict the address and the offset to map. static std::size_t get_page_size(); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //!Closes a previously opened memory mapping. Never throws void priv_close(); @@ -152,6 +229,7 @@ class mapped_region void* priv_map_address() const; std::size_t priv_map_size() const; bool priv_flush_param_check(std::size_t mapping_offset, void *&addr, std::size_t &numbytes) const; + bool priv_shrink_param_check(std::size_t bytes, bool from_back, void *&shrink_page_start, std::size_t &shrink_page_bytes); static void priv_size_from_mapping_size (offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size); static offset_t priv_page_offset_addr_fixup(offset_t page_offset, const void *&addr); @@ -180,10 +258,10 @@ class mapped_region template<int Dummy> static void destroy_syncs_in_range(const void *addr, std::size_t size); #endif - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -///@cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline void swap(mapped_region &x, mapped_region &y) { x.swap(y); } @@ -226,6 +304,38 @@ inline bool mapped_region::priv_flush_param_check return true; } +inline bool mapped_region::priv_shrink_param_check + (std::size_t bytes, bool from_back, void *&shrink_page_start, std::size_t &shrink_page_bytes) +{ + //Check some errors + if(m_base == 0 || bytes > m_size){ + return false; + } + else if(bytes == m_size){ + this->priv_close(); + return true; + } + else{ + const std::size_t page_size = mapped_region::get_page_size(); + if(from_back){ + const std::size_t new_pages = (m_size + m_page_offset - bytes - 1)/page_size + 1; + shrink_page_start = static_cast<char*>(this->priv_map_address()) + new_pages*page_size; + shrink_page_bytes = m_page_offset + m_size - new_pages*page_size; + m_size -= bytes; + } + else{ + shrink_page_start = this->priv_map_address(); + m_page_offset += bytes; + shrink_page_bytes = (m_page_offset/page_size)*page_size; + m_page_offset = m_page_offset % page_size; + m_size -= bytes; + m_base = static_cast<char *>(m_base) + bytes; + BOOST_ASSERT(shrink_page_bytes%page_size == 0); + } + return true; + } +} + inline void mapped_region::priv_size_from_mapping_size (offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size) { @@ -268,7 +378,7 @@ template<int dummy> inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size() { winapi::system_info info; - get_system_info(&info); + winapi::get_system_info(&info); return std::size_t(info.dwAllocationGranularity); } @@ -278,7 +388,8 @@ inline mapped_region::mapped_region ,mode_t mode ,offset_t offset ,std::size_t size - ,const void *address) + ,const void *address + ,map_options_t map_options) : m_base(0), m_size(0), m_page_offset(0), m_mode(mode) , m_file_or_mapping_hnd(ipcdetail::invalid_file()) { @@ -290,7 +401,7 @@ inline mapped_region::mapped_region //For "create_file_mapping" unsigned long protection = 0; //For "mapviewoffile" - unsigned long map_access = 0; + unsigned long map_access = map_options == default_map_options ? 0 : map_options; switch(mode) { @@ -356,7 +467,6 @@ inline mapped_region::mapped_region priv_size_from_mapping_size(mapping_size, offset, page_offset, size); } - //Map with new offsets and size void *base = winapi::map_view_of_file_ex (native_mapping_handle, @@ -398,13 +508,44 @@ inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbyte } //m_file_or_mapping_hnd can be a file handle or a mapping handle. //so flushing file buffers has only sense for files... - else if(async && m_file_or_mapping_hnd != winapi::invalid_handle_value && + else if(!async && m_file_or_mapping_hnd != winapi::invalid_handle_value && winapi::get_file_type(m_file_or_mapping_hnd) == winapi::file_type_disk){ return winapi::flush_file_buffers(m_file_or_mapping_hnd); } return true; } +inline bool mapped_region::shrink_by(std::size_t bytes, bool from_back) +{ + void *shrink_page_start; + std::size_t shrink_page_bytes; + if(!this->priv_shrink_param_check(bytes, from_back, shrink_page_start, shrink_page_bytes)){ + return false; + } + else if(shrink_page_bytes){ + //In Windows, we can't decommit the storage or release the virtual address space, + //the best we can do is try to remove some memory from the process working set. + //With a bit of luck we can free some physical memory. + unsigned long old_protect_ignored; + bool b_ret = winapi::virtual_unlock(shrink_page_start, shrink_page_bytes) + || (winapi::get_last_error() == winapi::error_not_locked); + (void)old_protect_ignored; + //Change page protection to forbid any further access + b_ret = b_ret && winapi::virtual_protect + (shrink_page_start, shrink_page_bytes, winapi::page_noaccess, old_protect_ignored); + return b_ret; + } + else{ + return true; + } +} + +inline bool mapped_region::advise(advice_types) +{ + //Windows has no madvise/posix_madvise equivalent + return false; +} + inline void mapped_region::priv_close() { if(m_base){ @@ -424,7 +565,7 @@ inline void mapped_region::priv_close() inline void mapped_region::dont_close_on_destruction() {} -#else //#if (defined BOOST_INTERPROCESS_WINDOWS) +#else //#if defined (BOOST_INTERPROCESS_WINDOWS) inline mapped_region::mapped_region() : m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false) @@ -440,7 +581,8 @@ inline mapped_region::mapped_region , mode_t mode , offset_t offset , std::size_t size - , const void *address) + , const void *address + , map_options_t map_options) : m_base(0), m_size(0), m_page_offset(0), m_mode(mode), m_is_xsi(false) { mapping_handle_t map_hnd = mapping.get_mapping_handle(); @@ -464,7 +606,7 @@ inline mapped_region::mapped_region throw interprocess_exception(err); } //Calculate flag - int flag = 0; + int flag = map_options == default_map_options ? 0 : map_options; if(m_mode == read_only){ flag |= SHM_RDONLY; } @@ -501,9 +643,17 @@ inline mapped_region::mapped_region priv_size_from_mapping_size(buf.st_size, offset, page_offset, size); } + #ifdef MAP_NOSYNC + #define BOOST_INTERPROCESS_MAP_NOSYNC MAP_NOSYNC + #else + #define BOOST_INTERPROCESS_MAP_NOSYNC 0 + #endif //MAP_NOSYNC + //Create new mapping int prot = 0; - int flags = 0; + int flags = map_options == default_map_options ? BOOST_INTERPROCESS_MAP_NOSYNC : map_options; + + #undef BOOST_INTERPROCESS_MAP_NOSYNC switch(mode) { @@ -562,14 +712,110 @@ inline mapped_region::mapped_region } } +inline bool mapped_region::shrink_by(std::size_t bytes, bool from_back) +{ + void *shrink_page_start = 0; + std::size_t shrink_page_bytes = 0; + if(m_is_xsi || !this->priv_shrink_param_check(bytes, from_back, shrink_page_start, shrink_page_bytes)){ + return false; + } + else if(shrink_page_bytes){ + //In UNIX we can decommit and free virtual address space. + return 0 == munmap(shrink_page_start, shrink_page_bytes); + } + else{ + return true; + } +} + inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes, bool async) { void *addr; - if(!this->priv_flush_param_check(mapping_offset, addr, numbytes)){ + if(m_is_xsi || !this->priv_flush_param_check(mapping_offset, addr, numbytes)){ return false; } //Flush it all - return msync( addr, numbytes, async ? MS_ASYNC : MS_SYNC) == 0; + return msync(addr, numbytes, async ? MS_ASYNC : MS_SYNC) == 0; +} + +inline bool mapped_region::advise(advice_types advice) +{ + int unix_advice = 0; + //Modes; 0: none, 2: posix, 1: madvise + const unsigned int mode_none = 0; + const unsigned int mode_padv = 1; + const unsigned int mode_madv = 2; + // Suppress "unused variable" warnings + (void)mode_padv; + (void)mode_madv; + unsigned int mode = mode_none; + //Choose advice either from POSIX (preferred) or native Unix + switch(advice){ + case advice_normal: + #if defined(POSIX_MADV_NORMAL) + unix_advice = POSIX_MADV_NORMAL; + mode = mode_padv; + #elif defined(MADV_NORMAL) + unix_advice = MADV_NORMAL; + mode = mode_madv; + #endif + break; + case advice_sequential: + #if defined(POSIX_MADV_SEQUENTIAL) + unix_advice = POSIX_MADV_SEQUENTIAL; + mode = mode_padv; + #elif defined(MADV_SEQUENTIAL) + unix_advice = MADV_SEQUENTIAL; + mode = mode_madv; + #endif + break; + case advice_random: + #if defined(POSIX_MADV_RANDOM) + unix_advice = POSIX_MADV_RANDOM; + mode = mode_padv; + #elif defined(MADV_RANDOM) + unix_advice = MADV_RANDOM; + mode = mode_madv; + #endif + break; + case advice_willneed: + #if defined(POSIX_MADV_WILLNEED) + unix_advice = POSIX_MADV_WILLNEED; + mode = mode_padv; + #elif defined(MADV_WILLNEED) + unix_advice = MADV_WILLNEED; + mode = mode_madv; + #endif + break; + case advice_dontneed: + #if defined(POSIX_MADV_DONTNEED) + unix_advice = POSIX_MADV_DONTNEED; + mode = mode_padv; + #elif defined(MADV_DONTNEED) && defined(BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS) + unix_advice = MADV_DONTNEED; + mode = mode_madv; + #endif + break; + default: + return false; + } + switch(mode){ + #if defined(POSIX_MADV_NORMAL) + case mode_padv: + return 0 == posix_madvise(this->priv_map_address(), this->priv_map_size(), unix_advice); + #endif + #if defined(MADV_NORMAL) + case mode_madv: + return 0 == madvise( + #if defined(BOOST_INTERPROCESS_MADVISE_USES_CADDR_T) + (caddr_t) + #endif + this->priv_map_address(), this->priv_map_size(), unix_advice); + #endif + default: + return false; + + } } inline void mapped_region::priv_close() @@ -591,7 +837,7 @@ inline void mapped_region::priv_close() inline void mapped_region::dont_close_on_destruction() { m_base = 0; } -#endif //##if (defined BOOST_INTERPROCESS_WINDOWS) +#endif //#if defined (BOOST_INTERPROCESS_WINDOWS) template<int dummy> const std::size_t mapped_region::page_size_holder<dummy>::PageSize @@ -611,7 +857,7 @@ inline void mapped_region::swap(mapped_region &other) ipcdetail::do_swap(this->m_size, other.m_size); ipcdetail::do_swap(this->m_page_offset, other.m_page_offset); ipcdetail::do_swap(this->m_mode, other.m_mode); - #if (defined BOOST_INTERPROCESS_WINDOWS) + #if defined (BOOST_INTERPROCESS_WINDOWS) ipcdetail::do_swap(this->m_file_or_mapping_hnd, other.m_file_or_mapping_hnd); #else ipcdetail::do_swap(this->m_is_xsi, other.m_is_xsi); @@ -623,9 +869,12 @@ struct null_mapped_region_function { bool operator()(void *, std::size_t , bool) const { return true; } + + std::size_t get_min_size() const + { return 0; } }; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/mem_algo/detail/mem_algo_common.hpp b/boost/interprocess/mem_algo/detail/mem_algo_common.hpp index 91d798145b..8af256aab9 100644 --- a/boost/interprocess/mem_algo/detail/mem_algo_common.hpp +++ b/boost/interprocess/mem_algo/detail/mem_algo_common.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP #define BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -24,8 +24,9 @@ #include <boost/interprocess/detail/type_traits.hpp> #include <boost/interprocess/detail/math_functions.hpp> #include <boost/interprocess/detail/utilities.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/min_max.hpp> +#include <boost/container/detail/multiallocation_chain.hpp> #include <boost/assert.hpp> #include <boost/static_assert.hpp> #include <algorithm> @@ -40,6 +41,37 @@ namespace boost { namespace interprocess { namespace ipcdetail { +template<class VoidPointer> +class basic_multiallocation_chain + : public boost::container::container_detail:: + basic_multiallocation_chain<VoidPointer> +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain) + typedef boost::container::container_detail:: + basic_multiallocation_chain<VoidPointer> base_t; + public: + + basic_multiallocation_chain() + : base_t() + {} + + basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other) + : base_t(::boost::move(static_cast<base_t&>(other))) + {} + + basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other) + { + this->base_t::operator=(::boost::move(static_cast<base_t&>(other))); + return *this; + } + + void *pop_front() + { + return boost::interprocess::ipcdetail::to_raw_pointer(this->base_t::pop_front()); + } +}; + + //!This class implements several allocation functions shared by different algorithms //!(aligned allocation, multiple allocation...). template<class MemoryAlgorithm> @@ -81,15 +113,15 @@ class memory_algorithm_common static size_type multiple_of_units(size_type size) { return get_rounded_size(size, Alignment); } - static multiallocation_chain allocate_many - (MemoryAlgorithm *memory_algo, size_type elem_bytes, size_type n_elements) + static void allocate_many + (MemoryAlgorithm *memory_algo, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) { - return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, 0); + return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, 0, chain); } - static void deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain chain) + static void deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain) { - return this_type::priv_deallocate_many(memory_algo, boost::move(chain)); + return this_type::priv_deallocate_many(memory_algo, chain); } static bool calculate_lcm_and_needs_backwards_lcmed @@ -187,19 +219,20 @@ class memory_algorithm_common return true; } - static multiallocation_chain allocate_many + static void allocate_many ( MemoryAlgorithm *memory_algo , const size_type *elem_sizes , size_type n_elements - , size_type sizeof_element) + , size_type sizeof_element + , multiallocation_chain &chain) { - return this_type::priv_allocate_many(memory_algo, elem_sizes, n_elements, sizeof_element); + this_type::priv_allocate_many(memory_algo, elem_sizes, n_elements, sizeof_element, chain); } static void* allocate_aligned (MemoryAlgorithm *memory_algo, size_type nbytes, size_type alignment) { - + //Ensure power of 2 if ((alignment & (alignment - size_type(1u))) != 0){ //Alignment is not power of two @@ -215,7 +248,7 @@ class memory_algorithm_common if(nbytes > UsableByPreviousChunk) nbytes -= UsableByPreviousChunk; - + //We can find a aligned portion if we allocate a block that has alignment //nbytes + alignment bytes or more. size_type minimum_allocation = max_value @@ -255,7 +288,6 @@ class memory_algorithm_common second->m_size = old_size - first->m_size; BOOST_ASSERT(second->m_size >= MinBlockUnits); memory_algo->priv_mark_new_allocated_block(first); - //memory_algo->priv_tail_size(first, first->m_size); memory_algo->priv_mark_new_allocated_block(second); memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(second)); } @@ -416,11 +448,12 @@ class memory_algorithm_common } private: - static multiallocation_chain priv_allocate_many + static void priv_allocate_many ( MemoryAlgorithm *memory_algo , const size_type *elem_sizes , size_type n_elements - , size_type sizeof_element) + , size_type sizeof_element + , multiallocation_chain &chain) { //Note: sizeof_element == 0 indicates that we want to //allocate n_elements of the same size "*elem_sizes" @@ -436,111 +469,114 @@ class memory_algorithm_common } else{ for(size_type i = 0; i < n_elements; ++i){ + if(multiplication_overflows(elem_sizes[i], sizeof_element)){ + total_request_units = 0; + break; + } elem_units = memory_algo->priv_get_total_units(elem_sizes[i]*sizeof_element); elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; + if(sum_overflows(total_request_units, elem_units)){ + total_request_units = 0; + break; + } total_request_units += elem_units; } } - multiallocation_chain chain; - - size_type low_idx = 0; - while(low_idx < n_elements){ - size_type total_bytes = total_request_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; - size_type min_allocation = (!sizeof_element) - ? elem_units - : memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); - min_allocation = min_allocation*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; - - size_type received_size; - std::pair<void *, bool> ret = memory_algo->priv_allocate - (boost::interprocess::allocate_new, min_allocation, total_bytes, received_size, 0); - if(!ret.first){ - break; - } + if(total_request_units && !multiplication_overflows(total_request_units, Alignment)){ + size_type low_idx = 0; + while(low_idx < n_elements){ + size_type total_bytes = total_request_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + size_type min_allocation = (!sizeof_element) + ? elem_units + : memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); + min_allocation = min_allocation*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + + size_type received_size; + std::pair<void *, bool> ret = memory_algo->priv_allocate + (boost::interprocess::allocate_new, min_allocation, total_bytes, received_size, 0); + if(!ret.first){ + break; + } - block_ctrl *block = memory_algo->priv_get_block(ret.first); - size_type received_units = (size_type)block->m_size; - char *block_address = reinterpret_cast<char*>(block); + block_ctrl *block = memory_algo->priv_get_block(ret.first); + size_type received_units = (size_type)block->m_size; + char *block_address = reinterpret_cast<char*>(block); - size_type total_used_units = 0; -// block_ctrl *prev_block = 0; - while(total_used_units < received_units){ - if(sizeof_element){ - elem_units = memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); - elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; - } - if(total_used_units + elem_units > received_units) - break; - total_request_units -= elem_units; - //This is the position where the new block must be created - block_ctrl *new_block = reinterpret_cast<block_ctrl *>(block_address); - assert_alignment(new_block); - - //The last block should take all the remaining space - if((low_idx + 1) == n_elements || - (total_used_units + elem_units + - ((!sizeof_element) - ? elem_units - : std::max(memory_algo->priv_get_total_units(elem_sizes[low_idx+1]*sizeof_element), ptr_size_units)) - ) > received_units){ - //By default, the new block will use the rest of the buffer - new_block->m_size = received_units - total_used_units; - memory_algo->priv_mark_new_allocated_block(new_block); - - //If the remaining units are bigger than needed and we can - //split it obtaining a new free memory block do it. - if((received_units - total_used_units) >= (elem_units + MemoryAlgorithm::BlockCtrlUnits)){ - size_type shrunk_received; - size_type shrunk_request = elem_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; - bool shrink_ok = shrink - (memory_algo - ,memory_algo->priv_get_user_buffer(new_block) - ,shrunk_request - ,shrunk_request - ,shrunk_received); - (void)shrink_ok; - //Shrink must always succeed with passed parameters - BOOST_ASSERT(shrink_ok); - //Some sanity checks - BOOST_ASSERT(shrunk_request == shrunk_received); - BOOST_ASSERT(elem_units == ((shrunk_request-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits)); - //"new_block->m_size" must have been reduced to elem_units by "shrink" - BOOST_ASSERT(new_block->m_size == elem_units); - //Now update the total received units with the reduction - received_units = elem_units + total_used_units; + size_type total_used_units = 0; + while(total_used_units < received_units){ + if(sizeof_element){ + elem_units = memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); + elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; } + if(total_used_units + elem_units > received_units) + break; + total_request_units -= elem_units; + //This is the position where the new block must be created + block_ctrl *new_block = reinterpret_cast<block_ctrl *>(block_address); + assert_alignment(new_block); + + //The last block should take all the remaining space + if((low_idx + 1) == n_elements || + (total_used_units + elem_units + + ((!sizeof_element) + ? elem_units + : std::max(memory_algo->priv_get_total_units(elem_sizes[low_idx+1]*sizeof_element), ptr_size_units)) + ) > received_units){ + //By default, the new block will use the rest of the buffer + new_block->m_size = received_units - total_used_units; + memory_algo->priv_mark_new_allocated_block(new_block); + + //If the remaining units are bigger than needed and we can + //split it obtaining a new free memory block do it. + if((received_units - total_used_units) >= (elem_units + MemoryAlgorithm::BlockCtrlUnits)){ + size_type shrunk_received; + size_type shrunk_request = elem_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + bool shrink_ok = shrink + (memory_algo + ,memory_algo->priv_get_user_buffer(new_block) + ,shrunk_request + ,shrunk_request + ,shrunk_received); + (void)shrink_ok; + //Shrink must always succeed with passed parameters + BOOST_ASSERT(shrink_ok); + //Some sanity checks + BOOST_ASSERT(shrunk_request == shrunk_received); + BOOST_ASSERT(elem_units == ((shrunk_request-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits)); + //"new_block->m_size" must have been reduced to elem_units by "shrink" + BOOST_ASSERT(new_block->m_size == elem_units); + //Now update the total received units with the reduction + received_units = elem_units + total_used_units; + } + } + else{ + new_block->m_size = elem_units; + memory_algo->priv_mark_new_allocated_block(new_block); + } + + block_address += new_block->m_size*Alignment; + total_used_units += (size_type)new_block->m_size; + //Check we have enough room to overwrite the intrusive pointer + BOOST_ASSERT((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(void_pointer)); + void_pointer p = new(memory_algo->priv_get_user_buffer(new_block))void_pointer(0); + chain.push_back(p); + ++low_idx; } - else{ - new_block->m_size = elem_units; - memory_algo->priv_mark_new_allocated_block(new_block); - } + //Sanity check + BOOST_ASSERT(total_used_units == received_units); + } - block_address += new_block->m_size*Alignment; - total_used_units += (size_type)new_block->m_size; - //Check we have enough room to overwrite the intrusive pointer - BOOST_ASSERT((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(void_pointer)); - void_pointer p = new(memory_algo->priv_get_user_buffer(new_block))void_pointer(0); - chain.push_back(p); - ++low_idx; - //prev_block = new_block; + if(low_idx != n_elements){ + priv_deallocate_many(memory_algo, chain); } - //Sanity check - BOOST_ASSERT(total_used_units == received_units); - } - - if(low_idx != n_elements){ - priv_deallocate_many(memory_algo, boost::move(chain)); } - return boost::move(chain); } - static void priv_deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain chain) + static void priv_deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain) { while(!chain.empty()){ - void *addr = to_raw_pointer(chain.front()); - chain.pop_front(); - memory_algo->priv_deallocate(addr); + memory_algo->priv_deallocate(to_raw_pointer(chain.pop_front())); } } }; diff --git a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp b/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp index e8b678d9f3..dd11bdbb50 100644 --- a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp +++ b/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MULTI_SIMPLE_SEQ_FIT_HPP #define BOOST_INTERPROCESS_MULTI_SIMPLE_SEQ_FIT_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -33,12 +33,12 @@ namespace interprocess { /*!This class implements the simple sequential fit algorithm with a simply linked list of free buffers.*/ template<class MutexFamily, class VoidPtr> -class multi_simple_seq_fit +class multi_simple_seq_fit : public ipcdetail::simple_seq_fit_impl<MutexFamily, VoidPtr> { typedef ipcdetail::simple_seq_fit_impl<MutexFamily, VoidPtr> base_t; public: - /*!Constructor. "size" is the total size of the managed memory segment, + /*!Constructor. "size" is the total size of the managed memory segment, "extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(multi_simple_seq_fit) offset that the allocator should not use at all.*/ multi_simple_seq_fit (size_type size, size_type extra_hdr_bytes) diff --git a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp b/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp index 7a2c7a83c1..c84d4e6fb7 100644 --- a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp +++ b/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP #define BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -84,10 +84,10 @@ class simple_seq_fit_impl { /*!Offset pointer to the next block.*/ block_ctrl_ptr m_next; - /*!This block's memory size (including block_ctrl + /*!This block's memory size (including block_ctrl header) in BasicSize units*/ size_type m_size; - + size_type get_user_bytes() const { return this->m_size*Alignment - BlockCtrlBytes; } @@ -124,7 +124,7 @@ class simple_seq_fit_impl } m_header; public: - /*!Constructor. "size" is the total size of the managed memory segment, + /*!Constructor. "size" is the total size of the managed memory segment, "extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit_impl) offset that the allocator should not use at all.*/ simple_seq_fit_impl (size_type size, size_type extra_hdr_bytes); @@ -159,7 +159,7 @@ class simple_seq_fit_impl std::pair<void *, bool> allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size,size_type &received_size, + size_type preferred_size,size_type &received_size, void *reuse_ptr = 0, size_type backwards_multiple = 1); /*!Returns the size of the buffer previously allocated pointed by ptr*/ @@ -170,8 +170,8 @@ class simple_seq_fit_impl void* allocate_aligned (size_type nbytes, size_type alignment); /*!Allocates bytes, if there is no more memory, it executes functor - f(size_type) to allocate a new segment to manage. The functor returns - std::pair<void*, size_type> indicating the base address and size of + f(size_type) to allocate a new segment to manage. The functor returns + std::pair<void*, size_type> indicating the base address and size of the new segment. If the new segment can't be allocated, allocate it will return 0.*/ void* multi_allocate(size_type nbytes); @@ -259,7 +259,7 @@ inline simple_seq_fit_impl<MutexFamily, VoidPointer>::~simple_seq_fit_impl() template<class MutexFamily, class VoidPointer> inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::grow(size_type extra_size) -{ +{ //Old highest address block's end offset size_type old_end = m_header.m_size/Alignment*Alignment; @@ -283,7 +283,7 @@ inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::grow(size_type extra_ template<class MutexFamily, class VoidPointer> inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_add_segment(void *addr, size_type size) -{ +{ //Check size BOOST_ASSERT(!(size < MinBlockSize)); if(size < MinBlockSize) @@ -293,7 +293,7 @@ inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_add_segment(void new_block->m_size = size/Alignment; new_block->m_next = 0; //Simulate this block was previously allocated - m_header.m_allocated += new_block->m_size*Alignment; + m_header.m_allocated += new_block->m_size*Alignment; //Return block and insert it in the free block list this->priv_deallocate(reinterpret_cast<char*>(new_block) + BlockCtrlBytes); } @@ -334,7 +334,7 @@ inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::clear_free_memory() //Iterate through all free portions do{ - //Just clear user the memory part reserved for the user + //Just clear user the memory part reserved for the user std::memset( reinterpret_cast<char*>(block) + BlockCtrlBytes , 0 , block->m_size*Alignment - BlockCtrlBytes); @@ -381,7 +381,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: template<class MutexFamily, class VoidPointer> inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: allocate(size_type nbytes) -{ +{ //----------------------- boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); //----------------------- @@ -392,7 +392,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: template<class MutexFamily, class VoidPointer> inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: allocate_aligned(size_type nbytes, size_type alignment) -{ +{ //----------------------- boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); //----------------------- @@ -402,7 +402,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: template<class MutexFamily, class VoidPointer> inline std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: allocation_command (boost::interprocess::allocation_type command, size_type min_size, - size_type preferred_size,size_type &received_size, + size_type preferred_size,size_type &received_size, void *reuse_ptr, size_type backwards_multiple) { //----------------------- @@ -451,11 +451,11 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: } //Now obtain the polymorphic functor that creates //new segments and try to allocate again. - boost::interprocess::multi_segment_services *p_services = + boost::interprocess::multi_segment_services *p_services = static_cast<boost::interprocess::multi_segment_services*> (void_pointer::find_group_data(group)); BOOST_ASSERT(p_services); - std::pair<void *, std::size_t> ret = + std::pair<void *, std::size_t> ret = p_services->create_new_segment(MinBlockSize > nbytes ? MinBlockSize : nbytes); if(ret.first){ priv_add_segment(ret.first, ret.second); @@ -498,11 +498,11 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: return 0; } - size_type needs_backwards = + size_type needs_backwards = ipcdetail::get_rounded_size(preferred_size - extra_forward, Alignment); - + if(!only_preferred_backwards){ - needs_backwards = + needs_backwards = max_value(ipcdetail::get_rounded_size(min_size - extra_forward, Alignment) ,min_value(prev->get_user_bytes(), needs_backwards)); } @@ -513,15 +513,15 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: if(!priv_expand(reuse_ptr, received_size, received_size, received_size)){ BOOST_ASSERT(0); } - + //We need a minimum size to split the previous one if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){ block_ctrl *new_block = reinterpret_cast<block_ctrl *> (reinterpret_cast<char*>(reuse) - needs_backwards - BlockCtrlBytes); new_block->m_next = 0; - new_block->m_size = + new_block->m_size = BlockCtrlSize + (needs_backwards + extra_forward)/Alignment; - prev->m_size = + prev->m_size = (prev->get_total_bytes() - needs_backwards)/Alignment - BlockCtrlSize; received_size = needs_backwards + extra_forward; m_header.m_allocated += needs_backwards + BlockCtrlBytes; @@ -553,7 +553,7 @@ std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: ,void *reuse_ptr) { if(command & boost::interprocess::shrink_in_place){ - bool success = + bool success = this->priv_shrink(reuse_ptr, limit_size, preferred_size, received_size); return std::pair<void *, bool> ((success ? reuse_ptr : 0), true); } @@ -643,7 +643,7 @@ inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl * } template<class MutexFamily, class VoidPointer> -inline +inline std::pair<typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl * ,typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *> simple_seq_fit_impl<MutexFamily, VoidPointer>:: @@ -724,7 +724,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: //We can fill expand. Merge both blocks, block->m_next = next_block->m_next; block->m_size = merged_size; - + //Find the previous free block of next_block block_ctrl *prev = &m_header.m_root; while(ipcdetail::to_raw_pointer(prev->m_next) != next_block){ @@ -733,7 +733,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: //Now insert merged block in the free list //This allows reusing allocation logic in this function - m_header.m_allocated -= old_block_size*Alignment; + m_header.m_allocated -= old_block_size*Alignment; prev->m_next = block; //Now use check and allocate to do the allocation logic @@ -747,7 +747,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: BOOST_ASSERT(0); return false; } - return true; + return true; } template<class MutexFamily, class VoidPointer> @@ -805,13 +805,13 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: //Now deallocate the new block to insert it in the free list this->priv_deallocate(reinterpret_cast<char*>(block)+BlockCtrlBytes); - return true; + return true; } template<class MutexFamily, class VoidPointer> inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: priv_allocate_aligned(size_type nbytes, size_type alignment) -{ +{ //Ensure power of 2 if ((alignment & (alignment - size_type(1u))) != 0){ //Alignment is not power of two @@ -823,8 +823,8 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: if(alignment <= Alignment){ return priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first; } - - size_type request = + + size_type request = nbytes + alignment + MinBlockSize*Alignment - BlockCtrlBytes; void *buffer = priv_allocate(boost::interprocess::allocate_new, request, request, ignore).first; if(!buffer) @@ -835,7 +835,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: char *aligned_portion = reinterpret_cast<char*> (reinterpret_cast<size_type>(static_cast<char*>(buffer) + alignment - 1) & -alignment); - char *pos = ((aligned_portion - reinterpret_cast<char*>(buffer)) >= (MinBlockSize*Alignment)) ? + char *pos = ((aligned_portion - reinterpret_cast<char*>(buffer)) >= (MinBlockSize*Alignment)) ? aligned_portion : (aligned_portion + alignment); block_ctrl *first = reinterpret_cast<block_ctrl*> @@ -867,7 +867,7 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_check_and_allocate bool found = false; if (block->m_size > upper_nunits){ - //This block is bigger than needed, split it in + //This block is bigger than needed, split it in //two blocks, the first's size will be (block->m_size-units) //the second's size (units) size_type total_size = block->m_size; @@ -918,7 +918,7 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr) //Let's get free block list. List is always sorted //by memory address to allow block merging. - //Pointer next always points to the first + //Pointer next always points to the first //(lower address) block block_ctrl_ptr prev = &m_header.m_root; block_ctrl_ptr pos = m_header.m_root.m_next; @@ -934,9 +934,9 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr) size_type total_size = Alignment*block->m_size; BOOST_ASSERT(m_header.m_allocated >= total_size); - + //Update used memory count - m_header.m_allocated -= total_size; + m_header.m_allocated -= total_size; //Let's find the previous and the next block of the block to deallocate //This ordering comparison must be done with original pointers @@ -949,7 +949,7 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr) //Try to combine with upper block if ((reinterpret_cast<char*>(ipcdetail::to_raw_pointer(block)) - + Alignment*block->m_size) == + + Alignment*block->m_size) == reinterpret_cast<char*>(ipcdetail::to_raw_pointer(pos))){ block->m_size += pos->m_size; @@ -961,7 +961,7 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr) //Try to combine with lower block if ((reinterpret_cast<char*>(ipcdetail::to_raw_pointer(prev)) - + Alignment*prev->m_size) == + + Alignment*prev->m_size) == reinterpret_cast<char*>(ipcdetail::to_raw_pointer(block))){ prev->m_size += block->m_size; prev->m_next = block->m_next; diff --git a/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp b/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp index c36916b72f..fa0e9caeb7 100644 --- a/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp +++ b/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP #define BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -60,7 +60,7 @@ class simple_seq_fit_impl simple_seq_fit_impl(); simple_seq_fit_impl(const simple_seq_fit_impl &); simple_seq_fit_impl &operator=(const simple_seq_fit_impl &); - + typedef typename boost::intrusive:: pointer_traits<VoidPointer>::template rebind_pointer<char>::type char_ptr; @@ -80,13 +80,12 @@ class simple_seq_fit_impl private: class block_ctrl; + friend class block_ctrl; + typedef typename boost::intrusive:: pointer_traits<VoidPointer>::template rebind_pointer<block_ctrl>::type block_ctrl_ptr; - class block_ctrl; - friend class block_ctrl; - //!Block control structure class block_ctrl { @@ -96,7 +95,7 @@ class simple_seq_fit_impl //!This block's memory size (including block_ctrl //!header) in BasicSize units size_type m_size; - + size_type get_user_bytes() const { return this->m_size*Alignment - BlockCtrlBytes; } @@ -142,32 +141,30 @@ class simple_seq_fit_impl //!Allocates bytes, returns 0 if there is not more memory void* allocate (size_type nbytes); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Multiple element allocation, same size - multiallocation_chain - allocate_many(size_type elem_bytes, size_type num_elements) + void allocate_many(size_type elem_bytes, size_type num_elements, multiallocation_chain &chain) { //----------------------- boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); //----------------------- - return algo_impl_t::allocate_many(this, elem_bytes, num_elements); + algo_impl_t::allocate_many(this, elem_bytes, num_elements, chain); } //!Multiple element allocation, different size - multiallocation_chain - allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element) + void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) { //----------------------- boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); //----------------------- - return algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element); + algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, chain); } //!Multiple element deallocation - void deallocate_many(multiallocation_chain chain); + void deallocate_many(multiallocation_chain &chain); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Deallocates previously allocated bytes void deallocate (void *addr); @@ -283,7 +280,7 @@ class simple_seq_fit_impl void priv_mark_new_allocated_block(block_ctrl *block); public: - static const size_type Alignment = ::boost::alignment_of< ::boost::detail::max_align>::value; + static const size_type Alignment = ::boost::alignment_of< ::boost::detail::max_align>::value; private: static const size_type BlockCtrlBytes = ipcdetail::ct_rounded_size<sizeof(block_ctrl), Alignment>::value; static const size_type BlockCtrlUnits = BlockCtrlBytes/Alignment; @@ -331,11 +328,11 @@ simple_seq_fit_impl<MutexFamily, VoidPointer> template<class MutexFamily, class VoidPointer> inline simple_seq_fit_impl<MutexFamily, VoidPointer>:: - simple_seq_fit_impl(size_type size, size_type extra_hdr_bytes) + simple_seq_fit_impl(size_type segment_size, size_type extra_hdr_bytes) { //Initialize sizes and counters m_header.m_allocated = 0; - m_header.m_size = size; + m_header.m_size = segment_size; m_header.m_extra_hdr_bytes = extra_hdr_bytes; //Initialize pointers @@ -344,7 +341,7 @@ inline simple_seq_fit_impl<MutexFamily, VoidPointer>:: m_header.m_root.m_next = reinterpret_cast<block_ctrl*> ((reinterpret_cast<char*>(this) + block1_off)); algo_impl_t::assert_alignment(ipcdetail::to_raw_pointer(m_header.m_root.m_next)); - m_header.m_root.m_next->m_size = (size - block1_off)/Alignment; + m_header.m_root.m_next->m_size = (segment_size - block1_off)/Alignment; m_header.m_root.m_next->m_next = &m_header.m_root; } @@ -426,7 +423,7 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::shrink_to_fit() (void)addr; BOOST_ASSERT(addr); BOOST_ASSERT(received_size == last_units*Alignment - AllocatedCtrlBytes); - + //Shrink it m_header.m_size /= Alignment; m_header.m_size -= last->m_size; @@ -462,16 +459,16 @@ void *simple_seq_fit_impl<MutexFamily, VoidPointer>:: } template<class MutexFamily, class VoidPointer> -inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_add_segment(void *addr, size_type size) -{ +inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_add_segment(void *addr, size_type segment_size) +{ algo_impl_t::assert_alignment(addr); //Check size - BOOST_ASSERT(!(size < MinBlockSize)); - if(size < MinBlockSize) + BOOST_ASSERT(!(segment_size < MinBlockSize)); + if(segment_size < MinBlockSize) return; //Construct big block using the new segment block_ctrl *new_block = static_cast<block_ctrl *>(addr); - new_block->m_size = size/Alignment; + new_block->m_size = segment_size/Alignment; new_block->m_next = 0; //Simulate this block was previously allocated m_header.m_allocated += new_block->m_size*Alignment; @@ -523,7 +520,7 @@ inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::zero_free_memory() //Iterate through all free portions do{ - //Just clear user the memory part reserved for the user + //Just clear user the memory part reserved for the user std::memset( priv_get_user_buffer(block) , 0 , block->get_user_bytes()); @@ -583,7 +580,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: template<class MutexFamily, class VoidPointer> inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: allocate_aligned(size_type nbytes, size_type alignment) -{ +{ //----------------------- boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); //----------------------- @@ -653,8 +650,7 @@ inline std::pair<void*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: template<class MutexFamily, class VoidPointer> inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::size_type -simple_seq_fit_impl<MutexFamily, VoidPointer>:: - size(const void *ptr) const +simple_seq_fit_impl<MutexFamily, VoidPointer>::size(const void *ptr) const { //We need no synchronization since this block is not going //to be modified @@ -698,7 +694,7 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: size_type needs_backwards = ipcdetail::get_rounded_size(preferred_size - extra_forward, Alignment); - + if(!only_preferred_backwards){ max_value(ipcdetail::get_rounded_size(min_size - extra_forward, Alignment) ,min_value(prev->get_user_bytes(), needs_backwards)); @@ -710,7 +706,7 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: if(!priv_expand(reuse_ptr, received_size, received_size, received_size)){ BOOST_ASSERT(0); } - + //We need a minimum size to split the previous one if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){ block_ctrl *new_block = reinterpret_cast<block_ctrl*> @@ -744,15 +740,13 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: template<class MutexFamily, class VoidPointer> inline void simple_seq_fit_impl<MutexFamily, VoidPointer>:: - deallocate_many(typename simple_seq_fit_impl<MutexFamily, VoidPointer>::multiallocation_chain chain) + deallocate_many(typename simple_seq_fit_impl<MutexFamily, VoidPointer>::multiallocation_chain &chain) { //----------------------- boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); //----------------------- while(!chain.empty()){ - void *addr = chain.front(); - chain.pop_front(); - this->priv_deallocate(addr); + this->priv_deallocate(to_raw_pointer(chain.pop_front())); } } @@ -969,7 +963,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: //We can fill expand. Merge both blocks, block->m_next = next_block->m_next; block->m_size = merged_size; - + //Find the previous free block of next_block block_ctrl *prev = &m_header.m_root; while(ipcdetail::to_raw_pointer(prev->m_next) != next_block){ @@ -978,7 +972,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: //Now insert merged block in the free list //This allows reusing allocation logic in this function - m_header.m_allocated -= old_block_size*Alignment; + m_header.m_allocated -= old_block_size*Alignment; prev->m_next = block; //Now use check and allocate to do the allocation logic @@ -992,7 +986,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: BOOST_ASSERT(0); return false; } - return true; + return true; } template<class MutexFamily, class VoidPointer> inline @@ -1071,9 +1065,9 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr) size_type total_size = Alignment*block->m_size; BOOST_ASSERT(m_header.m_allocated >= total_size); - + //Update used memory count - m_header.m_allocated -= total_size; + m_header.m_allocated -= total_size; //Let's find the previous and the next block of the block to deallocate //This ordering comparison must be done with original pointers diff --git a/boost/interprocess/mem_algo/rbtree_best_fit.hpp b/boost/interprocess/mem_algo/rbtree_best_fit.hpp index 7ccc642e29..fb04889c17 100644 --- a/boost/interprocess/mem_algo/rbtree_best_fit.hpp +++ b/boost/interprocess/mem_algo/rbtree_best_fit.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP #define BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -31,11 +31,12 @@ #include <boost/interprocess/detail/math_functions.hpp> #include <boost/interprocess/detail/type_traits.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> +#include <boost/type_traits/alignment_of.hpp> #include <boost/type_traits/type_with_alignment.hpp> +#include <boost/type_traits/make_unsigned.hpp> #include <boost/intrusive/pointer_traits.hpp> #include <boost/assert.hpp> #include <boost/static_assert.hpp> -#include <boost/type_traits.hpp> #include <algorithm> #include <utility> #include <climits> @@ -65,7 +66,7 @@ namespace interprocess { template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> class rbtree_best_fit { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable rbtree_best_fit(); rbtree_best_fit(const rbtree_best_fit &); @@ -81,20 +82,19 @@ class rbtree_best_fit pointer_traits<VoidPointer>::template rebind_pointer<char>::type char_ptr; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Shared mutex family used for the rest of the Interprocess framework typedef MutexFamily mutex_family; //!Pointer type to be used with the rest of the Interprocess framework typedef VoidPointer void_pointer; - typedef boost::container::container_detail:: - basic_multiallocation_chain<VoidPointer> multiallocation_chain; + typedef ipcdetail::basic_multiallocation_chain<VoidPointer> multiallocation_chain; typedef typename boost::intrusive::pointer_traits<char_ptr>::difference_type difference_type; typedef typename boost::make_unsigned<difference_type>::type size_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: @@ -132,7 +132,7 @@ class rbtree_best_fit { return size < block.m_size; } bool operator()(const block_ctrl &block, size_type size) const - { return block.m_size < size; } + { return block.m_size < size; } }; //!Shared mutex to protect memory allocate/deallocate @@ -141,6 +141,7 @@ class rbtree_best_fit <block_ctrl, bi::base_hook<TreeHook> >::type Imultiset; typedef typename Imultiset::iterator imultiset_iterator; + typedef typename Imultiset::const_iterator imultiset_const_iterator; //!This struct includes needed data and derives from //!mutex_type to allow EBO when using null mutex_type @@ -157,11 +158,11 @@ class rbtree_best_fit } m_header; friend class ipcdetail::memory_algorithm_common<rbtree_best_fit>; - + typedef ipcdetail::memory_algorithm_common<rbtree_best_fit> algo_impl_t; public: - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Constructor. "size" is the total size of the managed memory segment, //!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(rbtree_best_fit) @@ -179,34 +180,32 @@ class rbtree_best_fit //!Allocates bytes, returns 0 if there is not more memory void* allocate (size_type nbytes); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Experimental. Dont' use //!Multiple element allocation, same size - multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements) + void allocate_many(size_type elem_bytes, size_type num_elements, multiallocation_chain &chain) { - //----------------------- boost::interprocess::scoped_lock<mutex_type> guard(m_header); //----------------------- - return algo_impl_t::allocate_many(this, elem_bytes, num_elements); + algo_impl_t::allocate_many(this, elem_bytes, num_elements, chain); } //!Multiple element allocation, different size - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element) + void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) { - //----------------------- boost::interprocess::scoped_lock<mutex_type> guard(m_header); //----------------------- - return algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element); + algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, chain); } //!Multiple element allocation, different size - void deallocate_many(multiallocation_chain chain); + void deallocate_many(multiallocation_chain &chain); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Deallocates previously allocated bytes void deallocate (void *addr); @@ -253,7 +252,7 @@ class rbtree_best_fit //!Alignment must be power of 2 void* allocate_aligned (size_type nbytes, size_type alignment); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: static size_type priv_first_block_offset_from_this(const void *this_ptr, size_type extra_hdr_bytes); @@ -339,7 +338,7 @@ class rbtree_best_fit void priv_add_segment(void *addr, size_type size); public: - + static const size_type Alignment = !MemAlignment ? size_type(::boost::alignment_of< ::boost::detail::max_align>::value) : size_type(MemAlignment) @@ -362,12 +361,12 @@ class rbtree_best_fit //Make sure the maximum alignment is power of two BOOST_STATIC_ASSERT((0 == (Alignment & (Alignment - size_type(1u))))); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: static const size_type PayloadPerAllocation = AllocatedCtrlBytes - UsableByPreviousChunk; }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::size_type @@ -385,16 +384,16 @@ inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::size_ty template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: - priv_add_segment(void *addr, size_type size) -{ + priv_add_segment(void *addr, size_type segment_size) +{ //Check alignment algo_impl_t::check_alignment(addr); //Check size - BOOST_ASSERT(size >= (BlockCtrlBytes + EndCtrlBlockBytes)); + BOOST_ASSERT(segment_size >= (BlockCtrlBytes + EndCtrlBlockBytes)); //Initialize the first big block and the "end" node block_ctrl *first_big_block = new(addr)block_ctrl; - first_big_block->m_size = size/Alignment - EndCtrlBlockUnits; + first_big_block->m_size = segment_size/Alignment - EndCtrlBlockUnits; BOOST_ASSERT(first_big_block->m_size >= BlockCtrlUnits); //The "end" node is just a node of size 0 with the "end" bit set @@ -451,18 +450,18 @@ inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_c template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> inline rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: - rbtree_best_fit(size_type size, size_type extra_hdr_bytes) + rbtree_best_fit(size_type segment_size, size_type extra_hdr_bytes) { //Initialize the header m_header.m_allocated = 0; - m_header.m_size = size; + m_header.m_size = segment_size; m_header.m_extra_hdr_bytes = extra_hdr_bytes; //Now write calculate the offset of the first big block that will //cover the whole segment - BOOST_ASSERT(get_min_size(extra_hdr_bytes) <= size); + BOOST_ASSERT(get_min_size(extra_hdr_bytes) <= segment_size); size_type block1_off = priv_first_block_offset_from_this(this, extra_hdr_bytes); - priv_add_segment(reinterpret_cast<char*>(this) + block1_off, size - block1_off); + priv_add_segment(reinterpret_cast<char*>(this) + block1_off, segment_size - block1_off); } template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> @@ -570,7 +569,7 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::shrink_to_fit() size_type shrunk_border_offset = (size_type)(reinterpret_cast<char*>(last_block) - reinterpret_cast<char*>(this)) + EndCtrlBlockBytes; - + block_ctrl *new_end_block = last_block; algo_impl_t::assert_alignment(new_end_block); @@ -672,7 +671,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> inline void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: allocate(size_type nbytes) -{ +{ //----------------------- boost::interprocess::scoped_lock<mutex_type> guard(m_header); //----------------------- @@ -816,7 +815,6 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: block_ctrl *reuse = priv_get_block(reuse_ptr); //Sanity check - //BOOST_ASSERT(reuse->m_size == priv_tail_size(reuse)); algo_impl_t::assert_alignment(reuse); block_ctrl *prev_block; @@ -851,7 +849,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: if(!priv_expand(reuse_ptr, received_size, received_size, received_size2)){ BOOST_ASSERT(0); } - BOOST_ASSERT(received_size = received_size2); + BOOST_ASSERT(received_size == received_size2); } //We need a minimum size to split the previous one if(prev_block->m_size >= (needs_backwards_aligned/Alignment + BlockCtrlUnits)){ @@ -884,7 +882,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: received_size = needs_backwards_aligned + received_size; m_header.m_allocated += needs_backwards_aligned; - + //Check alignment algo_impl_t::assert_alignment(new_block); @@ -930,12 +928,12 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> inline void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: - deallocate_many(typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::multiallocation_chain chain) + deallocate_many(typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::multiallocation_chain &chain) { //----------------------- boost::interprocess::scoped_lock<mutex_type> guard(m_header); //----------------------- - algo_impl_t::deallocate_many(this, boost::move(chain)); + algo_impl_t::deallocate_many(this, chain); } template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> @@ -1043,8 +1041,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: //The block must be marked as allocated and the sizes must be equal BOOST_ASSERT(priv_is_allocated_block(block)); - //BOOST_ASSERT(old_block_units == priv_tail_size(block)); - + //Put this to a safe value received_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; if(received_size >= preferred_size || received_size >= min_size) @@ -1208,9 +1205,6 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_is_allocated_ (void)next_block_prev_allocated; BOOST_ASSERT(allocated == next_block_prev_allocated); } - else{ - block = block; - } #endif return allocated; } @@ -1228,9 +1222,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_is_prev_alloc block_ctrl *prev = priv_prev_block(block); (void)prev; BOOST_ASSERT(!prev->m_allocated); - } - else{ - block = block; + BOOST_ASSERT(prev->m_size == block->m_prev_size); } #endif return false; @@ -1284,7 +1276,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_check_and_al imultiset_iterator it_hint; if(it_old == m_header.m_imultiset.begin() - || (--imultiset_iterator(it_old))->m_size < rem_block->m_size){ + || (--imultiset_iterator(it_old))->m_size <= rem_block->m_size){ //option a: slow but secure //m_header.m_imultiset.insert(m_header.m_imultiset.erase(it_old), *rem_block); //option b: Construct an empty node and swap @@ -1298,7 +1290,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_check_and_al m_header.m_imultiset.erase(it_old); m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *rem_block); } - + } else if (block->m_size >= nunits){ m_header.m_imultiset.erase(it_old); @@ -1318,7 +1310,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_check_and_al //Clear the memory occupied by the tree hook, since this won't be //cleared with zero_free_memory TreeHook *t = static_cast<TreeHook*>(block); - //Just clear the memory part reserved for the user + //Just clear the memory part reserved for the user std::size_t tree_hook_offset_in_block = (char*)t - (char*)block; //volatile char *ptr = char *ptr = reinterpret_cast<char*>(block)+tree_hook_offset_in_block; @@ -1344,10 +1336,9 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_deallocate(vo if(!addr) return; block_ctrl *block = priv_get_block(addr); - + //The blocks must be marked as allocated and the sizes must be equal BOOST_ASSERT(priv_is_allocated_block(block)); -// BOOST_ASSERT(block->m_size == priv_tail_size(block)); //Check if alignment and block size are right algo_impl_t::assert_alignment(addr); @@ -1362,42 +1353,44 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_deallocate(vo block_ctrl *block_to_insert = block; //Get the next block - block_ctrl *next_block = priv_next_block(block); - bool merge_with_prev = !priv_is_prev_allocated(block); - bool merge_with_next = !priv_is_allocated_block(next_block); + block_ctrl *const next_block = priv_next_block(block); + const bool merge_with_prev = !priv_is_prev_allocated(block); + const bool merge_with_next = !priv_is_allocated_block(next_block); //Merge logic. First just update block sizes, then fix free blocks tree if(merge_with_prev || merge_with_next){ //Merge if the previous is free if(merge_with_prev){ //Get the previous block - block_ctrl *prev_block = priv_prev_block(block); - prev_block->m_size += block->m_size; - BOOST_ASSERT(prev_block->m_size >= BlockCtrlUnits); - block_to_insert = prev_block; + block_to_insert = priv_prev_block(block); + block_to_insert->m_size += block->m_size; + BOOST_ASSERT(block_to_insert->m_size >= BlockCtrlUnits); } //Merge if the next is free if(merge_with_next){ block_to_insert->m_size += next_block->m_size; BOOST_ASSERT(block_to_insert->m_size >= BlockCtrlUnits); - if(merge_with_prev) - m_header.m_imultiset.erase(Imultiset::s_iterator_to(*next_block)); + const imultiset_iterator next_it = Imultiset::s_iterator_to(*next_block); + if(merge_with_prev){ + m_header.m_imultiset.erase(next_it); + } + else{ + m_header.m_imultiset.replace_node(next_it, *block_to_insert); + } } - bool only_merge_next = !merge_with_prev && merge_with_next; - imultiset_iterator free_block_to_check_it - (Imultiset::s_iterator_to(only_merge_next ? *next_block : *block_to_insert)); - imultiset_iterator was_bigger_it(free_block_to_check_it); - //Now try to shortcut erasure + insertion (O(log(N))) with //a O(1) operation if merging does not alter tree positions - if(++was_bigger_it != m_header.m_imultiset.end() && - block_to_insert->m_size > was_bigger_it->m_size ){ - m_header.m_imultiset.erase(free_block_to_check_it); - m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *block_to_insert); + const imultiset_iterator block_to_check_it = Imultiset::s_iterator_to(*block_to_insert); + imultiset_const_iterator next_to_check_it(block_to_check_it), end_it(m_header.m_imultiset.end()); + + if(++next_to_check_it != end_it && block_to_insert->m_size > next_to_check_it->m_size){ + //Block is bigger than next, so move it + m_header.m_imultiset.erase(block_to_check_it); + m_header.m_imultiset.insert(end_it, *block_to_insert); } - else if(only_merge_next){ - m_header.m_imultiset.replace_node(free_block_to_check_it, *block_to_insert); + else{ + //Block size increment didn't violate tree invariants so there is nothing to fix } } else{ @@ -1406,7 +1399,7 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_deallocate(vo priv_mark_as_free_block(block_to_insert); } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/mem_algo/simple_seq_fit.hpp b/boost/interprocess/mem_algo/simple_seq_fit.hpp index 1085ca00ac..aaa5d37497 100644 --- a/boost/interprocess/mem_algo/simple_seq_fit.hpp +++ b/boost/interprocess/mem_algo/simple_seq_fit.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP #define BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -34,9 +34,9 @@ template<class MutexFamily, class VoidPointer> class simple_seq_fit : public ipcdetail::simple_seq_fit_impl<MutexFamily, VoidPointer> { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef ipcdetail::simple_seq_fit_impl<MutexFamily, VoidPointer> base_t; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: typedef typename base_t::size_type size_type; @@ -44,8 +44,8 @@ class simple_seq_fit //!Constructor. "size" is the total size of the managed memory segment, //!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit) //!offset that the allocator should not use at all.*/ - simple_seq_fit (size_type size, size_type extra_hdr_bytes) - : base_t(size, extra_hdr_bytes){} + simple_seq_fit(size_type segment_size, size_type extra_hdr_bytes) + : base_t(segment_size, extra_hdr_bytes){} }; } //namespace interprocess { diff --git a/boost/interprocess/offset_ptr.hpp b/boost/interprocess/offset_ptr.hpp index ac8da2c292..5f523ce521 100644 --- a/boost/interprocess/offset_ptr.hpp +++ b/boost/interprocess/offset_ptr.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2014. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP #define BOOST_INTERPROCESS_OFFSET_PTR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -26,6 +26,7 @@ #include <ostream> #include <istream> #include <iterator> +#include <iostream> #include <boost/aligned_storage.hpp> #include <boost/type_traits/alignment_of.hpp> @@ -35,6 +36,8 @@ namespace boost { +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Predeclarations template <class T> struct has_trivial_constructor; @@ -42,22 +45,209 @@ struct has_trivial_constructor; template <class T> struct has_trivial_destructor; +#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + namespace interprocess { +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +namespace ipcdetail { + + template<class OffsetType, std::size_t OffsetAlignment> + union offset_ptr_internal + { + explicit offset_ptr_internal(OffsetType off) + : m_offset(off) + {} + OffsetType m_offset; //Distance between this object and pointee address + typename ::boost::aligned_storage + < sizeof(OffsetType) + , (OffsetAlignment == offset_type_alignment) ? + ::boost::alignment_of<OffsetType>::value : OffsetAlignment + >::type alignment_helper; + }; + + //Note: using the address of a local variable to point to another address + //is not standard conforming and this can be optimized-away by the compiler. + //Non-inlining is a method to remain illegal but correct + + //Undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_XXX if your compiler can inline + //this code without breaking the library + + //////////////////////////////////////////////////////////////////////// + // + // offset_ptr_to_raw_pointer + // + //////////////////////////////////////////////////////////////////////// + #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR + #if defined(_MSC_VER) && (_MSC_VER >= 1800) && (defined(_M_AMD64) || defined(_M_X64)) + //Visual 2013 x64 optimizes more than we desire, so disable branchless option + #else + #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR + #endif + template<int Dummy> + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR + BOOST_INTERPROCESS_NEVER_INLINE + #elif defined(NDEBUG) + inline + #endif + void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, std::size_t offset) + { + typedef pointer_size_t_caster<void*> caster_t; + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR + if(offset == 1){ + return 0; + } + else{ + const caster_t caster((void*)this_ptr); + return caster_t(caster.size() + offset).pointer(); + } + #else + const caster_t caster((void*)this_ptr); + std::size_t target_offset = caster.size() + offset; + std::size_t mask = -std::size_t(offset != 1); + target_offset &= mask; + return caster_t(target_offset).pointer(); + #endif + } + + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR + #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR + #endif + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR + #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR + #endif + + //////////////////////////////////////////////////////////////////////// + // + // offset_ptr_to_offset + // + //////////////////////////////////////////////////////////////////////// + #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF + //Branchless seems slower in x86 + #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF + + template<int Dummy> + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF + BOOST_INTERPROCESS_NEVER_INLINE + #elif defined(NDEBUG) + inline + #endif + std::size_t offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr) + { + typedef pointer_size_t_caster<void*> caster_t; + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF + //offset == 1 && ptr != 0 is not legal for this pointer + if(!ptr){ + return 1; + } + else{ + const caster_t this_caster((void*)this_ptr); + const caster_t ptr_caster((void*)ptr); + std::size_t offset = ptr_caster.size() - this_caster.size(); + BOOST_ASSERT(offset != 1); + return offset; + } + #else + const caster_t this_caster((void*)this_ptr); + const caster_t ptr_caster((void*)ptr); + //std::size_t other = -std::size_t(ptr != 0); + //std::size_t offset = (ptr_caster.size() - this_caster.size()) & other; + //return offset + !other; + // + std::size_t offset = (ptr_caster.size() - this_caster.size() - 1) & -std::size_t(ptr != 0); + return ++offset; + #endif + } + + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF + #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF + #endif + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF + #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF + #endif + + //////////////////////////////////////////////////////////////////////// + // + // offset_ptr_to_offset_from_other + // + //////////////////////////////////////////////////////////////////////// + #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER + //Branchless seems slower in x86 + #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER + + template<int Dummy> + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER + BOOST_INTERPROCESS_NEVER_INLINE + #elif defined(NDEBUG) + inline + #endif + std::size_t offset_ptr_to_offset_from_other + (const volatile void *this_ptr, const volatile void *other_ptr, std::size_t other_offset) + { + typedef pointer_size_t_caster<void*> caster_t; + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER + if(other_offset == 1){ + return 1; + } + else{ + const caster_t this_caster((void*)this_ptr); + const caster_t other_caster((void*)other_ptr); + std::size_t offset = other_caster.size() - this_caster.size() + other_offset; + BOOST_ASSERT(offset != 1); + return offset; + } + #else + const caster_t this_caster((void*)this_ptr); + const caster_t other_caster((void*)other_ptr); + return ((other_caster.size() - this_caster.size()) & -std::size_t(other_offset != 1)) + other_offset; + #endif + } + + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER + #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER + #endif + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER + #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER + #endif + + //////////////////////////////////////////////////////////////////////// + // + // Let's assume cast to void and cv cast don't change any target address + // + //////////////////////////////////////////////////////////////////////// + template<class From, class To> + struct offset_ptr_maintains_address + { + static const bool value = ipcdetail::is_cv_same<From, To>::value + || ipcdetail::is_cv_same<void, To>::value; + }; + +} //namespace ipcdetail { +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + //!A smart pointer that stores the offset between between the pointer and the //!the object it points. This allows offset allows special properties, since //!the pointer is independent from the address address of the pointee, if the //!pointer and the pointee are still separated by the same offset. This feature //!converts offset_ptr in a smart pointer that can be placed in shared memory and //!memory mapped files mapped in different addresses in every process. +//! +//! \tparam PointedType The type of the pointee. +//! \tparam DifferenceType A signed integer type that can represent the arithmetic operations on the pointer +//! \tparam OffsetType An unsigned integer type that can represent the +//! distance between two pointers reinterpret_cast-ed as unsigned integers. In general this type +//! should be at least of the same size of std::uintptr_t. In some systems it's possible to communicate +//! between 32 and 64 bit processes using 64 bit offsets. +//! \tparam OffsetAlignment Alignment of the OffsetType stored inside. In some systems might be necessary +//! to align it to 64 bits in order to communicate 32 and 64 bit processes using 64 bit offsets. template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment> class offset_ptr { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> self_t; void unspecified_bool_type_func() const {} typedef void (self_t::*unspecified_bool_type)() const; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: typedef PointedType element_type; @@ -74,69 +264,111 @@ class offset_ptr public: //Public Functions + //!Default constructor (null pointer). + //!Never throws. + offset_ptr() + : internal(1) + {} + //!Constructor from raw pointer (allows "0" pointer conversion). //!Never throws. - offset_ptr(pointer ptr = 0) { this->set_offset(ptr); } + offset_ptr(pointer ptr) + : internal(static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(ptr, this))) + {} //!Constructor from other pointer. //!Never throws. template <class T> offset_ptr( T *ptr , typename ipcdetail::enable_if< ipcdetail::is_convertible<T*, PointedType*> >::type * = 0) - { this->set_offset(static_cast<PointedType*>(ptr)); } + : internal(static_cast<OffsetType> + (ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr), this))) + {} //!Constructor from other offset_ptr //!Never throws. offset_ptr(const offset_ptr& ptr) - { this->set_offset(ptr.get()); } + : internal(static_cast<OffsetType> + (ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset))) + {} //!Constructor from other offset_ptr. If pointers of pointee types are //!convertible, offset_ptrs will be convertibles. Never throws. - template<class T2, class P2, class O2, std::size_t A2> - offset_ptr( const offset_ptr<T2, P2, O2, A2> &ptr - , typename ipcdetail::enable_if< ipcdetail::is_convertible<T2*, PointedType*> >::type * = 0) - { this->set_offset(static_cast<PointedType*>(ptr.get())); } + template<class T2> + offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + , typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value + && ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value + >::type * = 0 + #endif + ) + : internal(static_cast<OffsetType> + (ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset()))) + {} + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Constructor from other offset_ptr. If pointers of pointee types are + //!convertible, offset_ptrs will be convertibles. Never throws. + template<class T2> + offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr + , typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value + && !ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value + >::type * = 0) + : internal(static_cast<OffsetType> + (ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr.get()), this))) + {} + + #endif //!Emulates static_cast operator. //!Never throws. template<class T2, class P2, class O2, std::size_t A2> offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::static_cast_tag) - { this->set_offset(static_cast<PointedType*>(r.get())); } + : internal(static_cast<OffsetType> + (ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(r.get()), this))) + {} //!Emulates const_cast operator. //!Never throws. template<class T2, class P2, class O2, std::size_t A2> offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::const_cast_tag) - { this->set_offset(const_cast<PointedType*>(r.get())); } + : internal(static_cast<OffsetType> + (ipcdetail::offset_ptr_to_offset<0>(const_cast<PointedType*>(r.get()), this))) + {} //!Emulates dynamic_cast operator. //!Never throws. template<class T2, class P2, class O2, std::size_t A2> offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::dynamic_cast_tag) - { this->set_offset(dynamic_cast<PointedType*>(r.get())); } + : internal(static_cast<OffsetType> + (ipcdetail::offset_ptr_to_offset<0>(dynamic_cast<PointedType*>(r.get()), this))) + {} //!Emulates reinterpret_cast operator. //!Never throws. template<class T2, class P2, class O2, std::size_t A2> offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::reinterpret_cast_tag) - { this->set_offset(reinterpret_cast<PointedType*>(r.get())); } + : internal(static_cast<OffsetType> + (ipcdetail::offset_ptr_to_offset<0>(reinterpret_cast<PointedType*>(r.get()), this))) + {} //!Obtains raw pointer from offset. //!Never throws. - pointer get()const - { return this->to_raw_pointer(); } + pointer get() const + { return (pointer)ipcdetail::offset_ptr_to_raw_pointer<0>(this, this->internal.m_offset); } offset_type get_offset() const - { return internal.m_offset; } + { return this->internal.m_offset; } //!Pointer-like -> operator. It can return 0 pointer. //!Never throws. - pointer operator->() const + pointer operator->() const { return this->get(); } //!Dereferencing operator, if it is a null offset_ptr behavior //! is undefined. Never throws. - reference operator* () const + reference operator* () const { pointer p = this->get(); reference r = *p; @@ -145,26 +377,56 @@ class offset_ptr //!Indexing operator. //!Never throws. - template<class T> - reference operator[](T idx) const + reference operator[](difference_type idx) const { return this->get()[idx]; } //!Assignment from pointer (saves extra conversion). //!Never throws. offset_ptr& operator= (pointer from) - { this->set_offset(from); return *this; } + { + this->internal.m_offset = + static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(from, this)); + return *this; + } //!Assignment from other offset_ptr. //!Never throws. - offset_ptr& operator= (const offset_ptr & pt) - { pointer p(pt.get()); (void)p; this->set_offset(p); return *this; } + offset_ptr& operator= (const offset_ptr & ptr) + { + this->internal.m_offset = + static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset)); + return *this; + } //!Assignment from related offset_ptr. If pointers of pointee types //! are assignable, offset_ptrs will be assignable. Never throws. - template<class T2, class P2, class O2, std::size_t A2> - typename ipcdetail::enable_if<ipcdetail::is_convertible<T2*, PointedType*>, offset_ptr&>::type - operator= (const offset_ptr<T2, P2, O2, A2> & ptr) - { this->set_offset(static_cast<PointedType*>(ptr.get())); return *this; } + template<class T2> + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value + && ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value + , offset_ptr&>::type + #else + offset_ptr& + #endif + operator= (const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr) + { + this->internal.m_offset = + static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset())); + return *this; + } + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + template<class T2> + typename ipcdetail::enable_if_c<ipcdetail::is_convertible<T2*, PointedType*>::value + && !ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value + , offset_ptr&>::type + operator= (const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr) + { + this->internal.m_offset = + static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr.get()), this)); + return *this; + } + #endif //!offset_ptr += difference_type. //!Never throws. @@ -173,8 +435,7 @@ class offset_ptr //!offset_ptr -= difference_type. //!Never throws. - template<class T> - offset_ptr &operator-= (T offset) + offset_ptr &operator-= (difference_type offset) { this->dec_offset(offset * sizeof (PointedType)); return *this; } //!++offset_ptr. @@ -185,7 +446,11 @@ class offset_ptr //!offset_ptr++. //!Never throws. offset_ptr operator++ (int) - { offset_ptr temp(*this); ++*this; return temp; } + { + offset_ptr tmp(*this); + this->inc_offset(sizeof (PointedType)); + return tmp; + } //!--offset_ptr. //!Never throws. @@ -195,17 +460,21 @@ class offset_ptr //!offset_ptr--. //!Never throws. offset_ptr operator-- (int) - { offset_ptr temp(*this); --*this; return temp; } + { + offset_ptr tmp(*this); + this->dec_offset(sizeof (PointedType)); + return tmp; + } //!safe bool conversion operator. //!Never throws. - operator unspecified_bool_type() const - { return this->get()? &self_t::unspecified_bool_type_func : 0; } + operator unspecified_bool_type() const + { return this->internal.m_offset != 1? &self_t::unspecified_bool_type_func : 0; } //!Not operator. Not needed in theory, but improves portability. //!Never throws bool operator! () const - { return this->get() == 0; } + { return this->internal.m_offset == 1; } //!Compatibility with pointer_traits //! @@ -220,23 +489,23 @@ class offset_ptr //!difference_type + offset_ptr //!operation - friend offset_ptr operator+(difference_type diff, const offset_ptr& right) - { offset_ptr tmp(right); tmp += diff; return tmp; } + friend offset_ptr operator+(difference_type diff, offset_ptr right) + { right += diff; return right; } //!offset_ptr + difference_type //!operation - friend offset_ptr operator+(const offset_ptr& left, difference_type diff) - { offset_ptr tmp(left); tmp += diff; return tmp; } + friend offset_ptr operator+(offset_ptr left, difference_type diff) + { left += diff; return left; } //!offset_ptr - diff //!operation - friend offset_ptr operator-(const offset_ptr &left, difference_type diff) - { offset_ptr tmp(left); tmp -= diff; return tmp; } + friend offset_ptr operator-(offset_ptr left, difference_type diff) + { left -= diff; return left; } //!offset_ptr - diff //!operation - friend offset_ptr operator-(difference_type diff, const offset_ptr &right) - { offset_ptr tmp(right); tmp -= diff; return tmp; } + friend offset_ptr operator-(difference_type diff, offset_ptr right) + { right -= diff; return right; } //!offset_ptr - offset_ptr //!operation @@ -308,65 +577,15 @@ class offset_ptr } private: - /// @cond - - //Note: using the address of a local variable to point to another address - //is not standard conforming and this can be optimized-away by the compiler. - //Non-inlining is a method to remain illegal and correct - #if defined(_MSC_VER) - __declspec(noinline) //this workaround is needed for MSVC compilers - #elif defined (__GNUC__)//this workaround is needed for GCC - __attribute__((__noinline__)) - #endif - void set_offset(const PointedType *ptr) - { - #if defined (__GNUC__) - //asm(""); //Prevents the function to be optimized-away (provokes an special "side-effect") - #endif - //offset == 1 && ptr != 0 is not legal for this pointer - if(!ptr){ - internal.m_offset = 1; - } - else{ - internal.m_offset = (OffsetType)((const char*)ptr - (const char*)(this)); - BOOST_ASSERT(internal.m_offset != 1); - } - } - - #if defined(_MSC_VER) && (_MSC_VER >= 1400) - __declspec(noinline) - #elif defined (__GNUC__) - __attribute__((__noinline__)) - #endif - PointedType * to_raw_pointer() const - { - #if defined (__GNUC__) - //asm(""); //Prevents the function to be optimized-away (provokes an special "side-effect") - #endif - return static_cast<PointedType *>( - static_cast<void*>( - (internal.m_offset == 1) ? - 0 : - (const_cast<char*>(reinterpret_cast<const char*>(this)) + internal.m_offset) - ) - ); - } - + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) void inc_offset(DifferenceType bytes) { internal.m_offset += bytes; } void dec_offset(DifferenceType bytes) { internal.m_offset -= bytes; } - union internal_type{ - OffsetType m_offset; //Distance between this object and pointee address - typename ::boost::aligned_storage - < sizeof(OffsetType) - , (OffsetAlignment == offset_type_alignment) ? - ::boost::alignment_of<OffsetType>::value : OffsetAlignment - >::type alignment_helper; - } internal; - /// @endcond + ipcdetail::offset_ptr_internal<OffsetType, OffsetAlignment> internal; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!operator<< @@ -387,41 +606,41 @@ inline std::basic_istream<E, T> & operator>> template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2> inline boost::interprocess::offset_ptr<T1, P1, O1, A1> static_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r) -{ +{ return boost::interprocess::offset_ptr<T1, P1, O1, A1> - (r, boost::interprocess::ipcdetail::static_cast_tag()); + (r, boost::interprocess::ipcdetail::static_cast_tag()); } //!Simulation of const_cast between pointers. Never throws. template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2> inline boost::interprocess::offset_ptr<T1, P1, O1, A1> const_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r) -{ +{ return boost::interprocess::offset_ptr<T1, P1, O1, A1> - (r, boost::interprocess::ipcdetail::const_cast_tag()); + (r, boost::interprocess::ipcdetail::const_cast_tag()); } //!Simulation of dynamic_cast between pointers. Never throws. template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2> inline boost::interprocess::offset_ptr<T1, P1, O1, A1> dynamic_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r) -{ +{ return boost::interprocess::offset_ptr<T1, P1, O1, A1> - (r, boost::interprocess::ipcdetail::dynamic_cast_tag()); + (r, boost::interprocess::ipcdetail::dynamic_cast_tag()); } //!Simulation of reinterpret_cast between pointers. Never throws. template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2> inline boost::interprocess::offset_ptr<T1, P1, O1, A1> reinterpret_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r) -{ +{ return boost::interprocess::offset_ptr<T1, P1, O1, A1> - (r, boost::interprocess::ipcdetail::reinterpret_cast_tag()); + (r, boost::interprocess::ipcdetail::reinterpret_cast_tag()); } } //namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!has_trivial_constructor<> == true_type specialization for optimizations template <class T, class P, class O, std::size_t A> @@ -437,22 +656,22 @@ struct has_trivial_destructor< boost::interprocess::offset_ptr<T, P, O, A> > static const bool value = true; }; -//#if !defined(_MSC_VER) || (_MSC_VER >= 1400) + namespace interprocess { -//#endif + //!to_raw_pointer() enables boost::mem_fn to recognize offset_ptr. //!Never throws. template <class T, class P, class O, std::size_t A> inline T * to_raw_pointer(boost::interprocess::offset_ptr<T, P, O, A> const & p) -{ return p.get(); } -//#if !defined(_MSC_VER) || (_MSC_VER >= 1400) +{ return ipcdetail::to_raw_pointer(p); } + } //namespace interprocess -//#endif -/// @endcond + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace boost { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace boost{ @@ -479,28 +698,34 @@ struct pointer_plus_bits; template<class T, class P, class O, std::size_t A, std::size_t NumBits> struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits> { - typedef boost::interprocess::offset_ptr<T, P, O, A> pointer; + typedef boost::interprocess::offset_ptr<T, P, O, A> pointer; + typedef ::boost::interprocess::pointer_size_t_caster<T*> caster_t; //Bits are stored in the lower bits of the pointer except the LSB, //because this bit is used to represent the null pointer. - static const std::size_t Mask = ((std::size_t(1) << NumBits)-1)<<1u; + static const std::size_t Mask = ((std::size_t(1) << NumBits) - 1) << 1u; static pointer get_pointer(const pointer &n) - { return reinterpret_cast<T*>(std::size_t(n.get()) & ~std::size_t(Mask)); } + { + caster_t caster(n.get()); + return pointer(caster_t(caster.size() & ~Mask).pointer()); + } - static void set_pointer(pointer &n, pointer p) + static void set_pointer(pointer &n, const pointer &p) { - std::size_t pint = std::size_t(p.get()); - BOOST_ASSERT(0 == (std::size_t(pint) & Mask)); - n = reinterpret_cast<T*>(pint | (std::size_t(n.get()) & std::size_t(Mask))); + caster_t n_caster(n.get()); + caster_t p_caster(p.get()); + BOOST_ASSERT(0 == (p_caster.size() & Mask)); + n = caster_t(p_caster.size() | (n_caster.size() & Mask)).pointer(); } static std::size_t get_bits(const pointer &n) - { return(std::size_t(n.get()) & std::size_t(Mask)) >> 1u; } + { return (caster_t(n.get()).size() & Mask) >> 1u; } static void set_bits(pointer &n, std::size_t b) { BOOST_ASSERT(b < (std::size_t(1) << NumBits)); - n = reinterpret_cast<T*>(std::size_t(get_pointer(n).get()) | (b << 1u)); + caster_t n_caster(n.get()); + n = caster_t((n_caster.size() & ~Mask) | (b << 1u)).pointer(); } }; @@ -510,8 +735,6 @@ struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits> template<class T, class U> struct pointer_to_other; - - //Backwards compatibility with pointer_to_other template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment, class U> struct pointer_to_other @@ -521,7 +744,7 @@ struct pointer_to_other }; } //namespace boost{ -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/permissions.hpp b/boost/interprocess/permissions.hpp index 745f8a8e0f..49ddbd09a7 100644 --- a/boost/interprocess/permissions.hpp +++ b/boost/interprocess/permissions.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,9 +11,9 @@ #ifndef BOOST_INTERPROCESS_PERMISSIONS_HPP #define BOOST_INTERPROCESS_PERMISSIONS_HPP -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -#if defined (_MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -27,7 +27,7 @@ #endif -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!\file //!Describes permissions class @@ -35,7 +35,7 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #if defined(BOOST_INTERPROCESS_WINDOWS) @@ -54,14 +54,14 @@ winapi::interprocess_all_access_security unrestricted_permissions_holder<Dummy>: #endif //defined BOOST_INTERPROCESS_WINDOWS -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!The permissions class represents permissions to be set to shared memory or //!files, that can be constructed form usual permission representations: //!a SECURITY_ATTRIBUTES pointer in windows or ORed rwx chmod integer in UNIX. class permissions { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #if defined(BOOST_INTERPROCESS_WINDOWS) typedef void* os_permissions_type; @@ -70,7 +70,7 @@ class permissions #endif os_permissions_type m_perm; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructs a permissions object from a user provided os-dependent @@ -90,26 +90,22 @@ class permissions //!for UNIX. void set_default() { - /// @cond #if defined (BOOST_INTERPROCESS_WINDOWS) m_perm = 0; #else m_perm = 0644; #endif - /// @endcond } //!Sets permissions to unrestricted access: //!A null DACL for windows or 0666 for UNIX. void set_unrestricted() { - /// @cond #if defined (BOOST_INTERPROCESS_WINDOWS) m_perm = &ipcdetail::unrestricted_permissions_holder<0>::unrestricted; #else m_perm = 0666; #endif - /// @endcond } //!Sets permissions from a user provided os-dependent diff --git a/boost/interprocess/segment_manager.hpp b/boost/interprocess/segment_manager.hpp index 8680a953e2..87c0041cf4 100644 --- a/boost/interprocess/segment_manager.hpp +++ b/boost/interprocess/segment_manager.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP #define BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -32,7 +32,7 @@ #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/smart_ptr/deleter.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #include <cstddef> //std::size_t #include <string> //char_traits @@ -69,15 +69,15 @@ class segment_manager_base typedef typename MemoryAlgorithm::void_pointer void_pointer; typedef typename MemoryAlgorithm::mutex_family mutex_family; typedef MemoryAlgorithm memory_algorithm; - - /// @cond - + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Experimental. Don't use typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain; typedef typename MemoryAlgorithm::difference_type difference_type; typedef typename MemoryAlgorithm::size_type size_type; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!This constant indicates the payload size //!associated with each allocation of the memory algorithm @@ -94,8 +94,8 @@ class segment_manager_base //!dynamic allocation //! //!Can throw - segment_manager_base(size_type size, size_type reserved_bytes) - : MemoryAlgorithm(size, reserved_bytes) + segment_manager_base(size_type sz, size_type reserved_bytes) + : MemoryAlgorithm(sz, reserved_bytes) { BOOST_ASSERT((sizeof(segment_manager_base<MemoryAlgorithm>) == sizeof(MemoryAlgorithm))); } @@ -120,52 +120,53 @@ class segment_manager_base void * allocate (size_type nbytes, std::nothrow_t) { return MemoryAlgorithm::allocate(nbytes); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Experimental. Dont' use. - //!Allocates n_elements of - //!elem_size bytes. Throws bad_alloc on failure. - multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements) + //!Allocates n_elements of elem_bytes bytes. + //!Throws bad_alloc on failure. chain.size() is not increased on failure. + void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) { - multiallocation_chain mem(MemoryAlgorithm::allocate_many(elem_bytes, num_elements)); - if(mem.empty()) throw bad_alloc(); - return boost::move(mem); + size_type prev_size = chain.size(); + MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); + if(!elem_bytes || chain.size() == prev_size){ + throw bad_alloc(); + } } - //!Allocates n_elements, each one of - //!element_lenghts[i]*sizeof_element bytes. Throws bad_alloc on failure. - multiallocation_chain allocate_many - (const size_type *element_lenghts, size_type n_elements, size_type sizeof_element = 1) + //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes. + //!Throws bad_alloc on failure. chain.size() is not increased on failure. + void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) { - multiallocation_chain mem(MemoryAlgorithm::allocate_many(element_lenghts, n_elements, sizeof_element)); - if(mem.empty()) throw bad_alloc(); - return boost::move(mem); + size_type prev_size = chain.size(); + MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, chain); + if(!sizeof_element || chain.size() == prev_size){ + throw bad_alloc(); + } } - //!Allocates n_elements of - //!elem_size bytes. Returns a default constructed iterator on failure. - multiallocation_chain allocate_many - (size_type elem_bytes, size_type num_elements, std::nothrow_t) - { return MemoryAlgorithm::allocate_many(elem_bytes, num_elements); } + //!Allocates n_elements of elem_bytes bytes. + //!Non-throwing version. chain.size() is not increased on failure. + void allocate_many(std::nothrow_t, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) + { MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); } //!Allocates n_elements, each one of - //!element_lenghts[i]*sizeof_element bytes. - //!Returns a default constructed iterator on failure. - multiallocation_chain allocate_many - (const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, std::nothrow_t) - { return MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element); } + //!element_lengths[i]*sizeof_element bytes. + //!Non-throwing version. chain.size() is not increased on failure. + void allocate_many(std::nothrow_t, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) + { MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, chain); } - //!Deallocates elements pointed by the - //!multiallocation iterator range. - void deallocate_many(multiallocation_chain chain) - { MemoryAlgorithm::deallocate_many(boost::move(chain)); } + //!Deallocates all elements contained in chain. + //!Never throws. + void deallocate_many(multiallocation_chain &chain) + { MemoryAlgorithm::deallocate_many(chain); } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc //!on failure void * allocate(size_type nbytes) - { + { void * ret = MemoryAlgorithm::allocate(nbytes); if(!ret) throw bad_alloc(); @@ -180,13 +181,15 @@ class segment_manager_base //!Allocates nbytes bytes. This function is only used in //!single-segment management. Throws bad_alloc when fails void * allocate_aligned(size_type nbytes, size_type alignment) - { + { void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment); if(!ret) throw bad_alloc(); return ret; } + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + template<class T> std::pair<T *, bool> allocation_command (boost::interprocess::allocation_type command, size_type limit_size, @@ -214,6 +217,8 @@ class segment_manager_base return ret; } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + //!Deallocates the bytes allocated with allocate/allocate_many() //!pointed by addr void deallocate (void *addr) @@ -248,7 +253,7 @@ class segment_manager_base size_type size(const void *ptr) const { return MemoryAlgorithm::size(ptr); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) protected: void * prot_anonymous_construct (size_type num, bool dothrow, ipcdetail::in_place_interface &table) @@ -293,7 +298,7 @@ class segment_manager_base void prot_anonymous_destroy(const void *object, ipcdetail::in_place_interface &table) { - //Get control data from associated with this object + //Get control data from associated with this object typedef ipcdetail::block_header<size_type> block_header_t; block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment); @@ -312,7 +317,7 @@ class segment_manager_base table.destroy_n(const_cast<void*>(object), ctrl_data->m_value_bytes/table.size, destroyed); this->deallocate(ctrl_data); } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!This object is placed in the beginning of memory segment and @@ -337,26 +342,26 @@ template<class CharType class segment_manager : public segment_manager_base<MemoryAlgorithm> { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable segment_manager(); segment_manager(const segment_manager &); segment_manager &operator=(const segment_manager &); - typedef segment_manager_base<MemoryAlgorithm> Base; - /// @endcond + typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: - typedef MemoryAlgorithm memory_algorithm; - typedef typename Base::void_pointer void_pointer; - typedef typename Base::size_type size_type; - typedef typename Base::difference_type difference_type; - typedef CharType char_type; + typedef MemoryAlgorithm memory_algorithm; + typedef typename segment_manager_base_t::void_pointer void_pointer; + typedef typename segment_manager_base_t::size_type size_type; + typedef typename segment_manager_base_t::difference_type difference_type; + typedef CharType char_type; typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type; - static const size_type PayloadPerAllocation = Base::PayloadPerAllocation; + static const size_type PayloadPerAllocation = segment_manager_base_t::PayloadPerAllocation; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef ipcdetail::block_header<size_type> block_header_t; typedef ipcdetail::index_config<CharType, MemoryAlgorithm> index_config_named; @@ -376,16 +381,16 @@ class segment_manager typedef ipcdetail::segment_manager_iterator_transform <typename unique_index_t::const_iterator ,is_intrusive_index<index_type>::value> unique_transform; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - typedef typename Base::mutex_family mutex_family; + typedef typename segment_manager_base_t::mutex_family mutex_family; typedef transform_iterator <typename named_index_t::const_iterator, named_transform> const_named_iterator; typedef transform_iterator <typename unique_index_t::const_iterator, unique_transform> const_unique_iterator; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Constructor proxy object definition helper class template<class T> @@ -401,52 +406,44 @@ class segment_manager typedef ipcdetail::named_proxy<segment_manager, T, true> type; }; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Constructor of the segment manager //!"size" is the size of the memory segment where //!the segment manager is being constructed. //!Can throw - segment_manager(size_type size) - : Base(size, priv_get_reserved_bytes()) - , m_header(static_cast<Base*>(get_this_pointer())) + explicit segment_manager(size_type segment_size) + : segment_manager_base_t(segment_size, priv_get_reserved_bytes()) + , m_header(static_cast<segment_manager_base_t*>(get_this_pointer())) { (void) anonymous_instance; (void) unique_instance; - BOOST_ASSERT(static_cast<const void*>(this) == static_cast<const void*>(static_cast<Base*>(this))); + //Check EBO is applied, it's required + const void * const this_addr = this; + const void *const segm_addr = static_cast<segment_manager_base_t*>(this); + (void)this_addr; (void)segm_addr; + BOOST_ASSERT( this_addr == segm_addr); } - //!Tries to find a previous named allocation. Returns the address - //!and the object count. On failure the first member of the - //!returned pair is 0. - template <class T> - std::pair<T*, size_type> find (const CharType* name) - { return this->priv_find_impl<T>(name, true); } - - //!Tries to find a previous unique allocation. Returns the address + //!Tries to find a previous named/unique allocation. Returns the address //!and the object count. On failure the first member of the //!returned pair is 0. template <class T> - std::pair<T*, size_type> find (const ipcdetail::unique_instance_t* name) + std::pair<T*, size_type> find (char_ptr_holder_t name) { return this->priv_find_impl<T>(name, true); } - //!Tries to find a previous named allocation. Returns the address + //!Tries to find a previous named/unique allocation. Returns the address //!and the object count. On failure the first member of the //!returned pair is 0. This search is not mutex-protected! + //!Use it only inside atomic_func() calls, where the internal mutex + //!is guaranteed to be locked. template <class T> - std::pair<T*, size_type> find_no_lock (const CharType* name) - { return this->priv_find_impl<T>(name, false); } - - //!Tries to find a previous unique allocation. Returns the address - //!and the object count. On failure the first member of the - //!returned pair is 0. This search is not mutex-protected! - template <class T> - std::pair<T*, size_type> find_no_lock (const ipcdetail::unique_instance_t* name) + std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name) { return this->priv_find_impl<T>(name, false); } //!Returns throwing "construct" proxy //!object template <class T> - typename construct_proxy<T>::type + typename construct_proxy<T>::type construct(char_ptr_holder_t name) { return typename construct_proxy<T>::type (this, name, false, true); } @@ -466,27 +463,27 @@ class segment_manager //!Returns no throwing "search or construct" //!proxy object template <class T> - typename construct_proxy<T>::type + typename construct_proxy<T>::type find_or_construct(char_ptr_holder_t name, std::nothrow_t) { return typename construct_proxy<T>::type (this, name, true, false); } //!Returns throwing "construct from iterators" proxy object template <class T> - typename construct_iter_proxy<T>::type + typename construct_iter_proxy<T>::type construct_it(char_ptr_holder_t name) { return typename construct_iter_proxy<T>::type (this, name, false, true); } //!Returns throwing "search or construct from iterators" //!proxy object template <class T> - typename construct_iter_proxy<T>::type + typename construct_iter_proxy<T>::type find_or_construct_it(char_ptr_holder_t name) { return typename construct_iter_proxy<T>::type (this, name, true, true); } //!Returns no throwing "construct from iterators" //!proxy object template <class T> - typename construct_iter_proxy<T>::type + typename construct_iter_proxy<T>::type construct_it(char_ptr_holder_t name, std::nothrow_t) { return typename construct_iter_proxy<T>::type (this, name, false, false); } @@ -499,7 +496,7 @@ class segment_manager //!Calls object function blocking recursive interprocess_mutex and guarantees that //!no new named_alloc or destroy will be executed by any process while - //!executing the object function call*/ + //!executing the object function call template <class Func> void atomic_func(Func &f) { scoped_lock<rmutex> guard(m_header); f(); } @@ -522,28 +519,26 @@ class segment_manager } } - //!Destroys a previously created unique instance. + //!Destroys a previously created named/unique instance. //!Returns false if the object was not present. template <class T> - bool destroy(const ipcdetail::unique_instance_t *) + bool destroy(char_ptr_holder_t name) { + BOOST_ASSERT(!name.is_anonymous()); ipcdetail::placement_destroy<T> dtor; - return this->priv_generic_named_destroy<char> - (typeid(T).name(), m_header.m_unique_index, dtor, is_intrusive_t()); - } - //!Destroys the named object with - //!the given name. Returns false if that object can't be found. - template <class T> - bool destroy(const CharType *name) - { - ipcdetail::placement_destroy<T> dtor; - return this->priv_generic_named_destroy<CharType> - (name, m_header.m_named_index, dtor, is_intrusive_t()); + if(name.is_unique()){ + return this->priv_generic_named_destroy<char> + ( typeid(T).name(), m_header.m_unique_index , dtor, is_intrusive_t()); + } + else{ + return this->priv_generic_named_destroy<CharType> + ( name.get(), m_header.m_named_index, dtor, is_intrusive_t()); + } } //!Destroys an anonymous, unique or named object - //!using it's address + //!using its address template <class T> void destroy_ptr(const T *p) { @@ -575,18 +570,18 @@ class segment_manager //!creation of "num" named objects in the managed memory segment. //!Can throw boost::interprocess::bad_alloc if there is no enough memory. void reserve_named_objects(size_type num) - { + { //------------------------------- scoped_lock<rmutex> guard(m_header); //------------------------------- - m_header.m_named_index.reserve(num); + m_header.m_named_index.reserve(num); } //!Preallocates needed index resources to optimize the //!creation of "num" unique objects in the managed memory segment. //!Can throw boost::interprocess::bad_alloc if there is no enough memory. void reserve_unique_objects(size_type num) - { + { //------------------------------- scoped_lock<rmutex> guard(m_header); //------------------------------- @@ -596,38 +591,38 @@ class segment_manager //!Calls shrink_to_fit in both named and unique object indexes //!to try to free unused memory from those indexes. void shrink_to_fit_indexes() - { + { //------------------------------- scoped_lock<rmutex> guard(m_header); //------------------------------- - m_header.m_named_index.shrink_to_fit(); - m_header.m_unique_index.shrink_to_fit(); + m_header.m_named_index.shrink_to_fit(); + m_header.m_unique_index.shrink_to_fit(); } //!Returns the number of named objects stored in //!the segment. size_type get_num_named_objects() - { + { //------------------------------- scoped_lock<rmutex> guard(m_header); //------------------------------- - return m_header.m_named_index.size(); + return m_header.m_named_index.size(); } //!Returns the number of unique objects stored in //!the segment. size_type get_num_unique_objects() - { + { //------------------------------- scoped_lock<rmutex> guard(m_header); //------------------------------- - return m_header.m_unique_index.size(); + return m_header.m_unique_index.size(); } //!Obtains the minimum size needed by the //!segment manager static size_type get_min_size() - { return Base::get_min_size(priv_get_reserved_bytes()); } + { return segment_manager_base_t::get_min_size(priv_get_reserved_bytes()); } //!Returns a constant iterator to the beginning of the information about //!the named allocations performed in this segment manager @@ -684,14 +679,14 @@ class segment_manager typedef boost::interprocess::deleter<T, segment_manager> type; }; - //!Returns an instance of the default allocator for type T - //!initialized that allocates memory from this segment manager. + //!Returns an instance of the default deleter for type T + //!that will delete an object constructed in this segment manager. template<class T> typename deleter<T>::type get_deleter() { return typename deleter<T>::type(this); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Generic named/anonymous new function. Offers all the possibilities, //!such as throwing, search before creating, and the constructor is @@ -713,20 +708,20 @@ class segment_manager //!returned pair is 0. template <class T> std::pair<T*, size_type> priv_find_impl (const CharType* name, bool lock) - { + { //The name can't be null, no anonymous object can be found by name BOOST_ASSERT(name != 0); ipcdetail::placement_destroy<T> table; - size_type size; + size_type sz; void *ret; if(name == reinterpret_cast<const CharType*>(-1)){ - ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, size, is_intrusive_t(), lock); + ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, sz, is_intrusive_t(), lock); } else{ - ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, size, is_intrusive_t(), lock); + ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, sz, is_intrusive_t(), lock); } - return std::pair<T*, size_type>(static_cast<T*>(ret), size); + return std::pair<T*, size_type>(static_cast<T*>(ret), sz); } //!Tries to find a previous unique allocation. Returns the address @@ -741,11 +736,8 @@ class segment_manager return std::pair<T*, size_type>(static_cast<T*>(ret), size); } - void *priv_generic_construct(const CharType *name, - size_type num, - bool try2find, - bool dothrow, - ipcdetail::in_place_interface &table) + void *priv_generic_construct + (const CharType *name, size_type num, bool try2find, bool dothrow, ipcdetail::in_place_interface &table) { void *ret; //Security overflow check @@ -799,13 +791,13 @@ class segment_manager static const CharType *priv_get_instance_name(block_header_t *ctrl_data) { boost::interprocess::allocation_type type = ctrl_data->alloc_type(); - if(type != named_type){ + if(type == anonymous_type){ BOOST_ASSERT((type == anonymous_type && ctrl_data->m_num_char == 0) || (type == unique_type && ctrl_data->m_num_char != 0) ); return 0; } CharType *name = static_cast<CharType*>(ctrl_data->template name<CharType>()); - + //Sanity checks BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharType)); BOOST_ASSERT(ctrl_data->m_num_char == std::char_traits<CharType>::length(name)); @@ -831,8 +823,8 @@ class segment_manager static size_type priv_get_reserved_bytes() { //Get the number of bytes until the end of (*this) - //beginning in the end of the Base base. - return sizeof(segment_manager) - sizeof(Base); + //beginning in the end of the segment_manager_base_t base. + return sizeof(segment_manager) - sizeof(segment_manager_base_t); } template <class CharT> @@ -840,13 +832,10 @@ class segment_manager (const CharT* name, IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::in_place_interface &table, - size_type &length, - ipcdetail::true_ is_intrusive, - bool use_lock) + size_type &length, ipcdetail::true_ is_intrusive, bool use_lock) { (void)is_intrusive; typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type; - typedef ipcdetail::index_key<CharT, void_pointer> index_key_t; typedef typename index_type::iterator index_it; //------------------------------- @@ -880,9 +869,7 @@ class segment_manager (const CharT* name, IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::in_place_interface &table, - size_type &length, - ipcdetail::false_ is_intrusive, - bool use_lock) + size_type &length, ipcdetail::false_ is_intrusive, bool use_lock) { (void)is_intrusive; typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type; @@ -918,8 +905,7 @@ class segment_manager bool priv_generic_named_destroy (block_header_t *block_header, IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, - ipcdetail::in_place_interface &table, - ipcdetail::true_ is_node_index) + ipcdetail::in_place_interface &table, ipcdetail::true_ is_node_index) { (void)is_node_index; typedef typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator index_it; @@ -943,15 +929,13 @@ class segment_manager template <class CharT> bool priv_generic_named_destroy(const CharT *name, IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, - ipcdetail::in_place_interface &table, - ipcdetail::true_ is_intrusive_index) + ipcdetail::in_place_interface &table, ipcdetail::true_ is_intrusive_index) { (void)is_intrusive_index; typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type; - typedef ipcdetail::index_key<CharT, void_pointer> index_key_t; typedef typename index_type::iterator index_it; typedef typename index_type::value_type intrusive_value_type; - + //------------------------------- scoped_lock<rmutex> guard(m_header); //------------------------------- @@ -972,7 +956,7 @@ class segment_manager void *memory = iv; void *values = ctrl_data->value(); std::size_t num = ctrl_data->m_value_bytes/table.size; - + //Sanity check BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0); BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char()); @@ -1061,21 +1045,17 @@ class segment_manager } //Call destructors and free memory - std::size_t destroyed; + std::size_t destroyed; table.destroy_n(values, num, destroyed); this->deallocate(memory); return true; } template<class CharT> - void * priv_generic_named_construct(unsigned char type, - const CharT *name, - size_type num, - bool try2find, - bool dothrow, - ipcdetail::in_place_interface &table, - IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, - ipcdetail::true_ is_intrusive) + void * priv_generic_named_construct + (unsigned char type, const CharT *name, size_type num, bool try2find, + bool dothrow, ipcdetail::in_place_interface &table, + IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::true_ is_intrusive) { (void)is_intrusive; std::size_t namelen = std::char_traits<CharT>::length(name); @@ -1184,7 +1164,7 @@ class segment_manager //the memory allocation as the intrusive value is built in that //memory value_eraser<index_type> v_eraser(index, it); - + //Construct array, this can throw ipcdetail::array_construct(ptr, num, table); @@ -1197,14 +1177,10 @@ class segment_manager //!Generic named new function for //!named functions template<class CharT> - void * priv_generic_named_construct(unsigned char type, - const CharT *name, - size_type num, - bool try2find, - bool dothrow, - ipcdetail::in_place_interface &table, - IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, - ipcdetail::false_ is_intrusive) + void * priv_generic_named_construct + (unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow, + ipcdetail::in_place_interface &table, + IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::false_ is_intrusive) { (void)is_intrusive; std::size_t namelen = std::char_traits<CharT>::length(name); @@ -1346,14 +1322,14 @@ class segment_manager { named_index_t m_named_index; unique_index_t m_unique_index; - - header_t(Base *restricted_segment_mngr) - : m_named_index (restricted_segment_mngr) - , m_unique_index(restricted_segment_mngr) + + header_t(segment_manager_base_t *segment_mngr_base) + : m_named_index (segment_mngr_base) + , m_unique_index(segment_mngr_base) {} } m_header; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; diff --git a/boost/interprocess/shared_memory_object.hpp b/boost/interprocess/shared_memory_object.hpp index f3bc7ba173..59ea343264 100644 --- a/boost/interprocess/shared_memory_object.hpp +++ b/boost/interprocess/shared_memory_object.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,15 +11,19 @@ #ifndef BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP #define BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/exceptions.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/interprocess_fwd.hpp> #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #include <boost/interprocess/permissions.hpp> #include <cstddef> #include <string> @@ -51,10 +55,10 @@ namespace interprocess { //!create mapped regions from the mapped files class shared_memory_object { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable and non-assignable BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_memory_object) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Default constructor. Represents an empty shared_memory_object. @@ -81,16 +85,17 @@ class shared_memory_object //!Does not throw shared_memory_object(BOOST_RV_REF(shared_memory_object) moved) : m_handle(file_handle_t(ipcdetail::invalid_file())) + , m_mode(read_only) { this->swap(moved); } //!Moves the ownership of "moved"'s shared memory to *this. //!After the call, "moved" does not represent any shared memory. //!Does not throw shared_memory_object &operator=(BOOST_RV_REF(shared_memory_object) moved) - { + { shared_memory_object tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps the shared_memory_objects. Does not throw @@ -99,7 +104,7 @@ class shared_memory_object //!Erases a shared memory object from the system. //!Returns false on error. Never throws static bool remove(const char *name); - + //!Sets the size of the shared memory mapping void truncate(offset_t length); @@ -125,25 +130,26 @@ class shared_memory_object //!Returns mapping handle. Never throws. mapping_handle_t get_mapping_handle() const; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //!Closes a previously opened file mapping. Never throws. void priv_close(); - //!Closes a previously opened file mapping. Never throws. + //!Opens or creates a shared memory object. bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm); file_handle_t m_handle; mode_t m_mode; std::string m_filename; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline shared_memory_object::shared_memory_object() : m_handle(file_handle_t(ipcdetail::invalid_file())) + , m_mode(read_only) {} inline shared_memory_object::~shared_memory_object() @@ -157,10 +163,10 @@ inline bool shared_memory_object::get_size(offset_t &size) const { return ipcdetail::get_file_size((file_handle_t)m_handle, size); } inline void shared_memory_object::swap(shared_memory_object &other) -{ +{ std::swap(m_handle, other.m_handle); std::swap(m_mode, other.m_mode); - m_filename.swap(other.m_filename); + m_filename.swap(other.m_filename); } inline mapping_handle_t shared_memory_object::get_mapping_handle() const @@ -178,7 +184,7 @@ inline bool shared_memory_object::priv_open_or_create { m_filename = filename; std::string shmfile; - ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, shmfile); + ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, shmfile); //Set accesses if (mode != read_write && mode != read_only){ @@ -219,7 +225,7 @@ inline bool shared_memory_object::remove(const char *filename) try{ //Make sure a temporary path is created for shared memory std::string shmfile; - ipcdetail::tmp_filename(filename, shmfile); + ipcdetail::shared_filepath(filename, shmfile); return ipcdetail::delete_file(shmfile.c_str()); } catch(...){ @@ -283,7 +289,7 @@ inline bool shared_memory_object::priv_open_or_create ipcdetail::add_leading_slash(filename, m_filename); } else{ - ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, m_filename); + ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, m_filename); } //Create new mapping @@ -318,20 +324,26 @@ inline bool shared_memory_object::priv_open_or_create break; case ipcdetail::DoOpenOrCreate: { - oflag |= O_CREAT; - //We need a loop to change permissions correctly using fchmod, since - //with "O_CREAT only" shm_open we don't know if we've created or opened the file. + //We need a create/open loop to change permissions correctly using fchmod, since + //with "O_CREAT" only we don't know if we've created or opened the shm. while(1){ - m_handle = shm_open(m_filename.c_str(), oflag, unix_perm); + //Try to create shared memory + m_handle = shm_open(m_filename.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm); + //If successful change real permissions if(m_handle >= 0){ ::fchmod(m_handle, unix_perm); - break; } + //If already exists, try to open else if(errno == EEXIST){ - if((m_handle = shm_open(m_filename.c_str(), oflag, unix_perm)) >= 0 || errno != ENOENT){ - break; + m_handle = shm_open(m_filename.c_str(), oflag, unix_perm); + //If open fails and errno tells the file does not exist + //(shm was removed between creation and opening tries), just retry + if(m_handle < 0 && errno == ENOENT){ + continue; } } + //Exit retries + break; } } break; @@ -343,7 +355,7 @@ inline bool shared_memory_object::priv_open_or_create } //Check for error - if(m_handle == -1){ + if(m_handle < 0){ error_info err = errno; this->priv_close(); throw interprocess_exception(err); @@ -357,7 +369,7 @@ inline bool shared_memory_object::priv_open_or_create inline bool shared_memory_object::remove(const char *filename) { try{ - std::string file_str; + std::string filepath; #if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY) const bool add_leading_slash = false; #elif defined(BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY) @@ -366,12 +378,12 @@ inline bool shared_memory_object::remove(const char *filename) const bool add_leading_slash = true; #endif if(add_leading_slash){ - ipcdetail::add_leading_slash(filename, file_str); + ipcdetail::add_leading_slash(filename, filepath); } else{ - ipcdetail::tmp_filename(filename, file_str); + ipcdetail::shared_filepath(filename, filepath); } - return 0 == shm_unlink(file_str.c_str()); + return 0 == shm_unlink(filepath.c_str()); } catch(...){ return false; @@ -396,8 +408,6 @@ inline void shared_memory_object::priv_close() #endif -///@endcond - //!A class that stores the name of a shared memory //!and calls shared_memory_object::remove(name) in its destructor //!Useful to remove temporary shared memory objects in the presence @@ -414,6 +424,8 @@ class remove_shared_memory_on_destroy { shared_memory_object::remove(m_name); } }; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/smart_ptr/deleter.hpp b/boost/interprocess/smart_ptr/deleter.hpp index 3a07ccd8f4..1a9e390018 100644 --- a/boost/interprocess/smart_ptr/deleter.hpp +++ b/boost/interprocess/smart_ptr/deleter.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. +// (C) Copyright Ion Gaztanaga 2007-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -13,7 +13,7 @@ #ifndef BOOST_INTERPROCESS_DELETER_HPP #define BOOST_INTERPROCESS_DELETER_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp b/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp index 9429613492..77ceda0c58 100644 --- a/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp +++ b/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp @@ -13,7 +13,7 @@ #ifndef BOOST_INTERPROCESS_BAD_WEAK_PTR_HPP_INCLUDED #define BOOST_INTERPROCESS_BAD_WEAK_PTR_HPP_INCLUDED -#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#if defined(_MSC_VER) # pragma once #endif @@ -36,7 +36,7 @@ class bad_weak_ptr { return "boost::interprocess::bad_weak_ptr"; } }; -} // namespace interprocess +} // namespace interprocess } // namespace boost #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/smart_ptr/detail/shared_count.hpp b/boost/interprocess/smart_ptr/detail/shared_count.hpp index 7daaee6ea4..aed83eb2ab 100644 --- a/boost/interprocess/smart_ptr/detail/shared_count.hpp +++ b/boost/interprocess/smart_ptr/detail/shared_count.hpp @@ -4,7 +4,7 @@ // // (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003 // (C) Copyright Peter Dimov 2004-2005 -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -16,7 +16,7 @@ // MS compatible compilers support #pragma once -#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#if defined(_MSC_VER) # pragma once #endif @@ -116,7 +116,7 @@ class shared_count } ~shared_count() // nothrow - { + { if(m_pi) m_pi->release(); } @@ -284,6 +284,7 @@ class weak_count weak_count & operator= (weak_count const & r) // nothrow { + m_px = r.m_px; counted_impl_ptr tmp = r.m_pi; if(tmp != 0) tmp->weak_add_ref(); if(m_pi != 0) m_pi->weak_release(); diff --git a/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp b/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp index 24d96ee482..47743c1b91 100644 --- a/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp +++ b/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. +// (C) Copyright Ion Gaztanaga 2007-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -12,6 +12,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED #define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED +#if defined(_MSC_VER) +# pragma once +#endif + # include <boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp> #endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED diff --git a/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp b/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp index edb39eeeb3..6ec1d56e59 100644 --- a/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp +++ b/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp @@ -3,13 +3,13 @@ // MS compatible compilers support #pragma once -#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#if defined(_MSC_VER) # pragma once #endif // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. // Copyright 2004-2005 Peter Dimov -// Copyright 2007-2011 Ion Gaztanaga +// Copyright 2007-2012 Ion Gaztanaga // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp b/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp index 6a46bb75e6..3e01be5531 100644 --- a/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp +++ b/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp @@ -3,7 +3,7 @@ // MS compatible compilers support #pragma once -#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#if defined(_MSC_VER) # pragma once #endif @@ -63,7 +63,7 @@ struct scoped_ptr_dealloc_functor { if (ptr) priv_deallocate(ptr, alloc_version()); } }; - + template<class A, class D> class sp_counted_impl_pd @@ -83,6 +83,8 @@ class sp_counted_impl_pd portable_rebind_alloc < const this_type >::type const_this_allocator; typedef typename this_allocator::pointer this_pointer; + typedef typename boost::intrusive:: + pointer_traits<this_pointer> this_pointer_traits; sp_counted_impl_pd( sp_counted_impl_pd const & ); sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & ); @@ -115,14 +117,13 @@ class sp_counted_impl_pd void destroy() // nothrow { - //Self destruction, so get a copy of the allocator - //(in the future we could move it) - this_allocator a_copy(*this); + //Self destruction, so move the allocator + this_allocator a_copy(::boost::move(static_cast<this_allocator&>(*this))); BOOST_ASSERT(a_copy == *this); - this_pointer this_ptr (this); + this_pointer this_ptr(this_pointer_traits::pointer_to(*this)); //Do it now! scoped_ptr< this_type, scoped_ptr_dealloc_functor<this_allocator> > - deleter(this_ptr, a_copy); + deleter_ptr(this_ptr, a_copy); typedef typename this_allocator::value_type value_type; ipcdetail::to_raw_pointer(this_ptr)->~value_type(); } diff --git a/boost/interprocess/smart_ptr/enable_shared_from_this.hpp b/boost/interprocess/smart_ptr/enable_shared_from_this.hpp index 9c8c7918f5..0ca3b0a390 100644 --- a/boost/interprocess/smart_ptr/enable_shared_from_this.hpp +++ b/boost/interprocess/smart_ptr/enable_shared_from_this.hpp @@ -3,7 +3,7 @@ // This file is the adaptation for Interprocess of boost/enable_shared_from_this.hpp // // (C) Copyright Peter Dimov 2002 -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -14,6 +14,10 @@ #ifndef BOOST_INTERPROCESS_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED #define BOOST_INTERPROCESS_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -34,7 +38,7 @@ namespace interprocess{ template<class T, class A, class D> class enable_shared_from_this { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) protected: enable_shared_from_this() {} @@ -47,7 +51,7 @@ class enable_shared_from_this ~enable_shared_from_this() {} - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: shared_ptr<T, A, D> shared_from_this() @@ -64,10 +68,10 @@ class enable_shared_from_this return p; } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef T element_type; mutable weak_ptr<element_type, A, D> _internal_weak_this; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; } // namespace interprocess diff --git a/boost/interprocess/smart_ptr/intrusive_ptr.hpp b/boost/interprocess/smart_ptr/intrusive_ptr.hpp index f6d5c8b77c..ff66512251 100644 --- a/boost/interprocess/smart_ptr/intrusive_ptr.hpp +++ b/boost/interprocess/smart_ptr/intrusive_ptr.hpp @@ -3,7 +3,7 @@ // This file is the adaptation for Interprocess of boost/intrusive_ptr.hpp // // (C) Copyright Peter Dimov 2001, 2002 -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -14,6 +14,10 @@ #ifndef BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED #define BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED +#if defined(_MSC_VER) +# pragma once +#endif + //!\file //!Describes an intrusive ownership pointer. @@ -56,12 +60,12 @@ class intrusive_ptr //!Provides the type of the stored pointer. typedef T element_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef VoidPointer VP; typedef intrusive_ptr this_type; typedef pointer this_type::*unspecified_bool_type; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Initializes internal pointer to 0. @@ -125,7 +129,7 @@ class intrusive_ptr this_type(rhs).swap(*this); return *this; } - + //!Returns a reference to the internal pointer. //!Does not throw pointer &get() @@ -166,10 +170,10 @@ class intrusive_ptr void swap(intrusive_ptr & rhs) { ipcdetail::do_swap(m_ptr, rhs.m_ptr); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: pointer m_ptr; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!Returns a.get() == b.get(). @@ -219,9 +223,9 @@ bool operator!=(const typename intrusive_ptr<T, VP>::pointer &a, template<class T, class VP> inline bool operator<(intrusive_ptr<T, VP> const & a, intrusive_ptr<T, VP> const & b) -{ +{ return std::less<typename intrusive_ptr<T, VP>::pointer>() - (a.get(), b.get()); + (a.get(), b.get()); } //!Exchanges the contents of the two intrusive_ptrs. @@ -277,7 +281,7 @@ inline boost::interprocess::intrusive_ptr<T, VP>reinterpret_pointer_cast } // namespace interprocess -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #if defined(_MSC_VER) && (_MSC_VER < 1400) //!Returns p.get(). @@ -287,7 +291,7 @@ inline T *to_raw_pointer(boost::interprocess::intrusive_ptr<T, VP> p) { return p.get(); } #endif -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } // namespace boost diff --git a/boost/interprocess/smart_ptr/scoped_ptr.hpp b/boost/interprocess/smart_ptr/scoped_ptr.hpp index a3755d3592..e628608c9a 100644 --- a/boost/interprocess/smart_ptr/scoped_ptr.hpp +++ b/boost/interprocess/smart_ptr/scoped_ptr.hpp @@ -4,7 +4,7 @@ // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // (C) Copyright Peter Dimov 2001, 2002 -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -15,6 +15,10 @@ #ifndef BOOST_INTERPROCESS_SCOPED_PTR_HPP_INCLUDED #define BOOST_INTERPROCESS_SCOPED_PTR_HPP_INCLUDED +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/detail/pointer_type.hpp> @@ -40,13 +44,13 @@ template<class T, class Deleter> class scoped_ptr : private Deleter { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) scoped_ptr(scoped_ptr const &); scoped_ptr & operator=(scoped_ptr const &); typedef scoped_ptr<T, Deleter> this_type; typedef typename ipcdetail::add_reference<T>::type reference; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: @@ -127,10 +131,10 @@ class scoped_ptr void swap(scoped_ptr & b) // never throws { ipcdetail::do_swap<Deleter>(*this, b); ipcdetail::do_swap(m_ptr, b.m_ptr); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: pointer m_ptr; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!Exchanges the internal pointer and deleter with other scoped_ptr @@ -147,7 +151,7 @@ typename scoped_ptr<T, D>::pointer to_raw_pointer(scoped_ptr<T, D> const & p) } // namespace interprocess -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #if defined(_MSC_VER) && (_MSC_VER < 1400) template<class T, class D> inline @@ -155,7 +159,7 @@ T *to_raw_pointer(boost::interprocess::scoped_ptr<T, D> const & p) { return p.get(); } #endif -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } // namespace boost diff --git a/boost/interprocess/smart_ptr/shared_ptr.hpp b/boost/interprocess/smart_ptr/shared_ptr.hpp index 5ede547a3f..fdf7235727 100644 --- a/boost/interprocess/smart_ptr/shared_ptr.hpp +++ b/boost/interprocess/smart_ptr/shared_ptr.hpp @@ -4,7 +4,7 @@ // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // (C) Copyright Peter Dimov 2001, 2002, 2003 -// (C) Copyright Ion Gaztanaga 2006-2011. +// (C) Copyright Ion Gaztanaga 2006-2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -16,6 +16,10 @@ #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED #define BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -24,7 +28,7 @@ #include <boost/assert.hpp> #include <boost/interprocess/smart_ptr/detail/shared_count.hpp> #include <boost/interprocess/detail/mpl.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/type_traits.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/smart_ptr/deleter.hpp> @@ -52,7 +56,7 @@ inline void sp_enable_shared_from_this (shared_count<T, VoidAllocator, Deleter> const & pn ,enable_shared_from_this<T, VoidAllocator, Deleter> *pe ,T *ptr) - + { (void)ptr; if(pe != 0){ @@ -88,10 +92,10 @@ inline void sp_enable_shared_from_this(shared_count<T, VoidAllocator, Deleter> c template<class T, class VoidAllocator, class Deleter> class shared_ptr { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef shared_ptr<T, VoidAllocator, Deleter> this_type; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: @@ -125,7 +129,7 @@ class shared_ptr //!Requirements: Deleter and A's copy constructor must not throw. explicit shared_ptr(const pointer&p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter()) : m_pn(p, a, d) - { + { //Check that the pointer passed is of the same type that //the pointer the allocator defines or it's a raw pointer typedef typename boost::intrusive:: @@ -171,7 +175,7 @@ class shared_ptr : m_pn() { this->swap(other); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template<class Y> shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::static_cast_tag) : m_pn( pointer(static_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer()))) @@ -193,7 +197,7 @@ class shared_ptr m_pn = ipcdetail::shared_count<T, VoidAllocator, Deleter>(); } } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Equivalent to shared_ptr(r).swap(*this). //!Never throws @@ -223,15 +227,15 @@ class shared_ptr //!This is equivalent to: //!this_type().swap(*this); void reset() - { - this_type().swap(*this); + { + this_type().swap(*this); } //!This is equivalent to: //!this_type(p, a, d).swap(*this); template<class Pointer> void reset(const Pointer &p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter()) - { + { //Check that the pointer passed is of the same type that //the pointer the allocator defines or it's a raw pointer typedef typename boost::intrusive:: @@ -239,7 +243,7 @@ class shared_ptr rebind_pointer<T>::type ParameterPointer; BOOST_STATIC_ASSERT((ipcdetail::is_same<pointer, ParameterPointer>::value) || (ipcdetail::is_pointer<Pointer>::value)); - this_type(p, a, d).swap(*this); + this_type(p, a, d).swap(*this); } template<class Y> @@ -263,14 +267,14 @@ class shared_ptr pointer get() const // never throws { return m_pn.to_raw_pointer(); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) // implicit conversion to "bool" void unspecified_bool_type_func() const {} typedef void (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const // never throws { return !m_pn.to_raw_pointer() ? 0 : &this_type::unspecified_bool_type_func; } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Not operator. //!Returns true if this->get() != 0, false otherwise @@ -295,7 +299,7 @@ class shared_ptr void swap(shared_ptr<T, VoidAllocator, Deleter> & other) // never throws { m_pn.swap(other.m_pn); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template<class T2, class A2, class Deleter2> bool _internal_less(shared_ptr<T2, A2, Deleter2> const & rhs) const @@ -313,7 +317,7 @@ class shared_ptr template<class T2, class A2, class Deleter2> friend class weak_ptr; ipcdetail::shared_count<T, VoidAllocator, Deleter> m_pn; // reference counter - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; // shared_ptr template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline @@ -404,7 +408,7 @@ inline typename managed_shared_ptr<T, ManagedMemory>::type } // namespace interprocess -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #if defined(_MSC_VER) && (_MSC_VER < 1400) // to_raw_pointer() enables boost::mem_fn to recognize shared_ptr @@ -413,7 +417,7 @@ T * to_raw_pointer(boost::interprocess::shared_ptr<T, VoidAllocator, Deleter> co { return p.get(); } #endif -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } // namespace boost diff --git a/boost/interprocess/smart_ptr/unique_ptr.hpp b/boost/interprocess/smart_ptr/unique_ptr.hpp index 89cdb1e6e2..9e51c93508 100644 --- a/boost/interprocess/smart_ptr/unique_ptr.hpp +++ b/boost/interprocess/smart_ptr/unique_ptr.hpp @@ -1,11 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// -// I, Howard Hinnant, hereby place this code in the public domain. -////////////////////////////////////////////////////////////////////////////// -// -// This file is the adaptation for Interprocess of -// Howard Hinnant's unique_ptr emulation code. // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2014. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -16,509 +11,22 @@ #ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED #define BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> -#include <boost/assert.hpp> -#include <boost/interprocess/detail/utilities.hpp> -#include <boost/interprocess/detail/pointer_type.hpp> -#include <boost/move/move.hpp> -#include <boost/compressed_pair.hpp> -#include <boost/static_assert.hpp> -#include <boost/interprocess/detail/mpl.hpp> -#include <boost/interprocess/detail/type_traits.hpp> -#include <boost/interprocess/smart_ptr/deleter.hpp> -#include <cstddef> +#include <boost/move/unique_ptr.hpp> //!\file -//!Describes the smart pointer unique_ptr +//!This header provides utilities to define a unique_ptr that plays nicely with managed segments. namespace boost{ namespace interprocess{ -/// @cond -template <class T, class D> class unique_ptr; - -namespace ipcdetail { - -template <class T> struct unique_ptr_error; - -template <class T, class D> -struct unique_ptr_error<const unique_ptr<T, D> > -{ - typedef unique_ptr<T, D> type; -}; - -} //namespace ipcdetail { -/// @endcond - -//!Template unique_ptr stores a pointer to an object and deletes that object -//!using the associated deleter when it is itself destroyed (such as when -//!leaving block scope. -//! -//!The unique_ptr provides a semantics of strict ownership. A unique_ptr owns the -//!object it holds a pointer to. -//! -//!A unique_ptr is not CopyConstructible, nor CopyAssignable, however it is -//!MoveConstructible and Move-Assignable. -//! -//!The uses of unique_ptr include providing exception safety for dynamically -//!allocated memory, passing ownership of dynamically allocated memory to a -//!function, and returning dynamically allocated memory from a function -//! -//!A client-supplied template argument D must be a -//!function pointer or functor for which, given a value d of type D and a pointer -//!ptr to a type T*, the expression d(ptr) is -//!valid and has the effect of deallocating the pointer as appropriate for that -//!deleter. D may also be an lvalue-reference to a deleter. -//! -//!If the deleter D maintains state, it is intended that this state stay with -//!the associated pointer as ownership is transferred -//!from unique_ptr to unique_ptr. The deleter state need never be copied, -//!only moved or swapped as pointer ownership -//!is moved around. That is, the deleter need only be MoveConstructible, -//!MoveAssignable, and Swappable, and need not be CopyConstructible -//!(unless copied into the unique_ptr) nor CopyAssignable. -template <class T, class D> -class unique_ptr -{ - /// @cond - struct nat {int for_bool_;}; - typedef typename ipcdetail::add_reference<D>::type deleter_reference; - typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference; - /// @endcond - - public: - - typedef T element_type; - typedef D deleter_type; - typedef typename ipcdetail::pointer_type<T, D>::type pointer; - - //!Requires: D must be default constructible, and that construction must not - //!throw an exception. D must not be a reference type. - //! - //!Effects: Constructs a unique_ptr which owns nothing. - //! - //!Postconditions: get() == 0. get_deleter() returns a reference to a - //!default constructed deleter D. - //! - //!Throws: nothing. - unique_ptr() - : ptr_(pointer(0)) - {} - - //!Requires: The expression D()(p) must be well formed. The default constructor - //!of D must not throw an exception. - //! - //!D must not be a reference type. - //! - //!Effects: Constructs a unique_ptr which owns p. - //! - //!Postconditions: get() == p. get_deleter() returns a reference to a default constructed deleter D. - //! - //!Throws: nothing. - explicit unique_ptr(pointer p) - : ptr_(p) - {} - - //!Requires: The expression d(p) must be well formed. - //! - //!Postconditions: get() == p. get_deleter() returns a reference to the - //!internally stored deleter. If D is a - //!reference type then get_deleter() returns a reference to the lvalue d. - //! - //!Throws: nothing. - unique_ptr(pointer p - ,typename ipcdetail::if_<ipcdetail::is_reference<D> - ,D - ,typename ipcdetail::add_reference<const D>::type>::type d) - : ptr_(p, d) - {} - - //!Requires: If the deleter is not a reference type, construction of the - //!deleter D from an lvalue D must not throw an exception. - //! - //!Effects: Constructs a unique_ptr which owns the pointer which u owns - //!(if any). If the deleter is not a reference type, it is move constructed - //!from u's deleter, otherwise the reference is copy constructed from u's deleter. - //! - //!After the construction, u no longer owns a pointer. - //![ Note: The deleter constructor can be implemented with - //! boost::forward<D>. -end note ] - //! - //!Postconditions: get() == value u.get() had before the construction. - //!get_deleter() returns a reference to the internally stored deleter which - //!was constructed from u.get_deleter(). If D is a reference type then get_- - //!deleter() and u.get_deleter() both reference the same lvalue deleter. - //! - //!Throws: nothing. - unique_ptr(BOOST_RV_REF(unique_ptr) u) - : ptr_(u.release(), boost::forward<D>(u.get_deleter())) - {} - - //!Requires: If D is not a reference type, construction of the deleter - //!D from an rvalue of type E must be well formed - //!and not throw an exception. If D is a reference type, then E must be - //!the same type as D (diagnostic required). unique_ptr<U, E>::pointer - //!must be implicitly convertible to pointer. - //! - //!Effects: Constructs a unique_ptr which owns the pointer which u owns - //!(if any). If the deleter is not a reference - //!type, it is move constructed from u's deleter, otherwise the reference - //!is copy constructed from u's deleter. - //! - //!After the construction, u no longer owns a pointer. - //! - //!postconditions get() == value u.get() had before the construction, - //!modulo any required offset adjustments - //!resulting from the cast from U* to T*. get_deleter() returns a reference to the internally stored deleter which - //!was constructed from u.get_deleter(). - //! - //!Throws: nothing. - template <class U, class E> - unique_ptr(BOOST_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u, - typename ipcdetail::enable_if_c< - ipcdetail::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value && - ipcdetail::is_convertible<E, D>::value && - ( - !ipcdetail::is_reference<D>::value || - ipcdetail::is_same<D, E>::value - ) - , - nat - >::type = nat()) - : ptr_(const_cast<unique_ptr<U,E>&>(u).release(), boost::move<D>(u.get_deleter())) - {} - - //!Effects: If get() == 0 there are no effects. Otherwise get_deleter()(get()). - //! - //!Throws: nothing. - ~unique_ptr() - { reset(); } - - // assignment - - //!Requires: Assignment of the deleter D from an rvalue D must not throw an exception. - //! - //!Effects: reset(u.release()) followed by a move assignment from u's deleter to - //!this deleter. - //! - //!Postconditions: This unique_ptr now owns the pointer which u owned, and u no - //!longer owns it. - //! - //!Returns: *this. - //! - //!Throws: nothing. - unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u) - { - reset(u.release()); - ptr_.second() = boost::move(u.get_deleter()); - return *this; - } - - //!Requires: Assignment of the deleter D from an rvalue D must not - //!throw an exception. U* must be implicitly convertible to T*. - //! - //!Effects: reset(u.release()) followed by a move assignment from - //!u's deleter to this deleter. If either D or E is - //!a reference type, then the referenced lvalue deleter participates - //!in the move assignment. - //! - //!Postconditions: This unique_ptr now owns the pointer which u owned, - //!and u no longer owns it. - //! - //!Returns: *this. - //! - //!Throws: nothing. - template <class U, class E> - unique_ptr& operator=(BOOST_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u) - { - reset(u.release()); - ptr_.second() = boost::move(u.get_deleter()); - return *this; - } - - //!Assigns from the literal 0 or NULL. - //! - //!Effects: reset(). - //! - //!Postcondition: get() == 0 - //! - //!Returns: *this. - //! - //!Throws: nothing. - unique_ptr& operator=(int nat::*) - { - reset(); - return *this; - } - - //!Requires: get() != 0. - //!Returns: *get(). - //!Throws: nothing. - typename ipcdetail::add_reference<T>::type operator*() const - { return *ptr_.first(); } - - //!Requires: get() != 0. - //!Returns: get(). - //!Throws: nothing. - pointer operator->() const - { return ptr_.first(); } - - //!Returns: The stored pointer. - //!Throws: nothing. - pointer get() const - { return ptr_.first(); } - - //!Returns: A reference to the stored deleter. - //! - //!Throws: nothing. - deleter_reference get_deleter() - { return ptr_.second(); } - - //!Returns: A const reference to the stored deleter. - //! - //!Throws: nothing. - deleter_const_reference get_deleter() const - { return ptr_.second(); } - - //!Returns: An unspecified value that, when used in boolean - //!contexts, is equivalent to get() != 0. - //! - //!Throws: nothing. - operator int nat::*() const - { return ptr_.first() ? &nat::for_bool_ : 0; } - - //!Postcondition: get() == 0. - //! - //!Returns: The value get() had at the start of the call to release. - //! - //!Throws: nothing. - pointer release() - { - pointer tmp = ptr_.first(); - ptr_.first() = 0; - return tmp; - } - - //!Effects: If p == get() there are no effects. Otherwise get_deleter()(get()). - //! - //!Postconditions: get() == p. - //! - //!Throws: nothing. - void reset(pointer p = 0) - { - if (ptr_.first() != p){ - if (ptr_.first()) - ptr_.second()(ptr_.first()); - ptr_.first() = p; - } - } - - //!Requires: The deleter D is Swappable and will not throw an exception under swap. - //! - //!Effects: The stored pointers of this and u are exchanged. - //! The stored deleters are swapped (unqualified). - //!Throws: nothing. - void swap(unique_ptr& u) - { ptr_.swap(u.ptr_); } - - /// @cond - private: - boost::compressed_pair<pointer, D> ptr_; - BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr) - template <class U, class E> unique_ptr(unique_ptr<U, E>&); - template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0); - - template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&); - template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&); - /// @endcond -}; -/* -template <class T, class D> -class unique_ptr<T[], D> -{ - struct nat {int for_bool_;}; - typedef typename ipcdetail::add_reference<D>::type deleter_reference; - typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference; -public: - typedef T element_type; - typedef D deleter_type; - typedef typename ipcdetail::pointer_type<T, D>::type pointer; - - // constructors - unique_ptr() : ptr_(pointer()) {} - explicit unique_ptr(pointer p) : ptr_(p) {} - unique_ptr(pointer p, typename if_< - boost::is_reference<D>, - D, - typename ipcdetail::add_reference<const D>::type>::type d) - : ptr_(p, d) {} - unique_ptr(const unique_ptr& u) - : ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {} - - // destructor - ~unique_ptr() {reset();} - - // assignment - unique_ptr& operator=(const unique_ptr& cu) - { - unique_ptr& u = const_cast<unique_ptr&>(cu); - reset(u.release()); - ptr_.second() = u.get_deleter(); - return *this; - } - unique_ptr& operator=(int nat::*) - { - reset(); - return *this; - } - - // observers - typename ipcdetail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];} - pointer get() const {return ptr_.first();} - deleter_reference get_deleter() {return ptr_.second();} - deleter_const_reference get_deleter() const {return ptr_.second();} - operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;} - - // modifiers - pointer release() - { - pointer tmp = ptr_.first(); - ptr_.first() = 0; - return tmp; - } - void reset(pointer p = 0) - { - if (ptr_.first() != p) - { - if (ptr_.first()) - ptr_.second()(ptr_.first()); - ptr_.first() = p; - } - } - void swap(unique_ptr& u) {ptr_.swap(u.ptr_);} -private: - boost::compressed_pair<pointer, D> ptr_; - - template <class U, class E> unique_ptr(U p, E, - typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0); - template <class U> explicit unique_ptr(U, - typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0); - - unique_ptr(unique_ptr&); - template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0); - - unique_ptr& operator=(unique_ptr&); - template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&); -}; - -template <class T, class D, std::size_t N> -class unique_ptr<T[N], D> -{ - struct nat {int for_bool_;}; - typedef typename ipcdetail::add_reference<D>::type deleter_reference; - typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference; -public: - typedef T element_type; - typedef D deleter_type; - typedef typename ipcdetail::pointer_type<T, D>::type pointer; - static const std::size_t size = N; - - // constructors - unique_ptr() : ptr_(0) {} - explicit unique_ptr(pointer p) : ptr_(p) {} - unique_ptr(pointer p, typename if_< - boost::is_reference<D>, - D, - typename ipcdetail::add_reference<const D>::type>::type d) - : ptr_(p, d) {} - unique_ptr(const unique_ptr& u) - : ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {} - - // destructor - ~unique_ptr() {reset();} - - // assignment - unique_ptr& operator=(const unique_ptr& cu) - { - unique_ptr& u = const_cast<unique_ptr&>(cu); - reset(u.release()); - ptr_.second() = u.get_deleter(); - return *this; - } - unique_ptr& operator=(int nat::*) - { - reset(); - return *this; - } - - // observers - typename ipcdetail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];} - pointer get() const {return ptr_.first();} - deleter_reference get_deleter() {return ptr_.second();} - deleter_const_reference get_deleter() const {return ptr_.second();} - operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;} - - // modifiers - pointer release() - { - pointer tmp = ptr_.first(); - ptr_.first() = 0; - return tmp; - } - void reset(pointer p = 0) - { - if (ptr_.first() != p) - { - if (ptr_.first()) - ptr_.second()(ptr_.first(), N); - ptr_.first() = p; - } - } - void swap(unique_ptr& u) {ptr_.swap(u.ptr_);} -private: - boost::compressed_pair<pointer, D> ptr_; - - template <class U, class E> unique_ptr(U p, E, - typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0); - template <class U> explicit unique_ptr(U, - typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0); - - unique_ptr(unique_ptr&); - template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0); - - unique_ptr& operator=(unique_ptr&); - template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&); -}; -*/ -template <class T, class D> inline -void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) -{ x.swap(y); } - -template <class T1, class D1, class T2, class D2> inline -bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ return x.get() == y.get(); } - -template <class T1, class D1, class T2, class D2> inline -bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ return x.get() != y.get(); } - -template <class T1, class D1, class T2, class D2> inline -bool operator <(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ return x.get() < y.get(); } - -template <class T1, class D1, class T2, class D2> inline -bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ return x.get() <= y.get(); } - -template <class T1, class D1, class T2, class D2> inline -bool operator >(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ return x.get() > y.get(); } - -template <class T1, class D1, class T2, class D2> inline -bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ return x.get() >= y.get(); } - +//For backwards compatibility +using ::boost::movelib::unique_ptr; //!Returns the type of a unique pointer //!of type T with boost::interprocess::deleter deleter @@ -526,7 +34,7 @@ bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) template<class T, class ManagedMemory> struct managed_unique_ptr { - typedef unique_ptr + typedef boost::movelib::unique_ptr < T , typename ManagedMemory::template deleter<T>::type > type; diff --git a/boost/interprocess/smart_ptr/weak_ptr.hpp b/boost/interprocess/smart_ptr/weak_ptr.hpp index 5202ede91c..e4c47cb253 100644 --- a/boost/interprocess/smart_ptr/weak_ptr.hpp +++ b/boost/interprocess/smart_ptr/weak_ptr.hpp @@ -3,7 +3,7 @@ // This file is the adaptation for Interprocess of boost/weak_ptr.hpp // // (C) Copyright Peter Dimov 2001, 2002, 2003 -// (C) Copyright Ion Gaztanaga 2006-2011. +// (C) Copyright Ion Gaztanaga 2006-2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -15,6 +15,10 @@ #ifndef BOOST_INTERPROCESS_WEAK_PTR_HPP_INCLUDED #define BOOST_INTERPROCESS_WEAK_PTR_HPP_INCLUDED +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -50,7 +54,7 @@ namespace interprocess{ template<class T, class A, class D> class weak_ptr { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: // Borland 5.5.1 specific workarounds typedef weak_ptr<T, A, D> this_type; @@ -61,7 +65,7 @@ class weak_ptr <T>::type reference; typedef typename ipcdetail::add_reference <T>::type const_reference; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: typedef T element_type; @@ -99,7 +103,7 @@ class weak_ptr template<class Y> weak_ptr(weak_ptr<Y, A, D> const & r) : m_pn(r.m_pn) // never throws - { + { //Construct a temporary shared_ptr so that nobody //can destroy the value while constructing this const shared_ptr<T, A, D> &ref = r.lock(); @@ -126,7 +130,7 @@ class weak_ptr //!implied guarantees) via different means, without creating a temporary. template<class Y> weak_ptr & operator=(weak_ptr<Y, A, D> const & r) // never throws - { + { //Construct a temporary shared_ptr so that nobody //can destroy the value while constructing this const shared_ptr<T, A, D> &ref = r.lock(); @@ -174,7 +178,7 @@ class weak_ptr //!testing purposes, not for production code. long use_count() const // never throws { return m_pn.use_count(); } - + //!Returns: Returns: use_count() == 0. //! //!Throws: nothing. @@ -195,11 +199,11 @@ class weak_ptr void swap(this_type & other) // never throws { ipcdetail::do_swap(m_pn, other.m_pn); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template<class T2, class A2, class D2> bool _internal_less(weak_ptr<T2, A2, D2> const & rhs) const { return m_pn < rhs.m_pn; } - + template<class Y> void _internal_assign(const ipcdetail::shared_count<Y, A, D> & pn2) { @@ -213,7 +217,7 @@ class weak_ptr template<class T2, class A2, class D2> friend class weak_ptr; ipcdetail::weak_count<T, A, D> m_pn; // reference counter - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; // weak_ptr template<class T, class A, class D, class U, class A2, class D2> inline diff --git a/boost/interprocess/streams/bufferstream.hpp b/boost/interprocess/streams/bufferstream.hpp index 3ae9f5e2dc..cb3e637939 100644 --- a/boost/interprocess/streams/bufferstream.hpp +++ b/boost/interprocess/streams/bufferstream.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -8,7 +8,7 @@ // ////////////////////////////////////////////////////////////////////////////// // -// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005. +// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012. // Changed internal SGI string to a buffer. Added efficient // internal buffer get/set/swap functions, so that we can obtain/establish the // internal buffer without any reallocation or copy. Kill those temporaries! @@ -35,6 +35,10 @@ #ifndef BOOST_INTERPROCESS_BUFFERSTREAM_HPP #define BOOST_INTERPROCESS_BUFFERSTREAM_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -42,7 +46,7 @@ #include <ios> #include <istream> #include <ostream> -#include <string> // char traits +#include <string> // char traits #include <cstddef> // ptrdiff_t #include <boost/assert.hpp> #include <boost/interprocess/interprocess_fwd.hpp> @@ -74,10 +78,10 @@ class basic_bufferbuf //!Constructor. Assigns formatting buffer. //!Does not throw. - explicit basic_bufferbuf(CharT *buffer, std::size_t length, + explicit basic_bufferbuf(CharT *buf, std::size_t length, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) - : base_t(), m_mode(mode), m_buffer(buffer), m_length(length) + : base_t(), m_mode(mode), m_buffer(buf), m_length(length) { this->set_pointers(); } virtual ~basic_bufferbuf(){} @@ -90,10 +94,10 @@ class basic_bufferbuf //!Sets the underlying buffer to a new value //!Does not throw. - void buffer(CharT *buffer, std::size_t length) - { m_buffer = buffer; m_length = length; this->set_pointers(); } + void buffer(CharT *buf, std::size_t length) + { m_buffer = buf; m_length = length; this->set_pointers(); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: void set_pointers() { @@ -177,7 +181,7 @@ class basic_bufferbuf { bool in = false; bool out = false; - + const std::ios_base::openmode inout = std::ios_base::in | std::ios_base::out; @@ -245,14 +249,17 @@ class basic_bufferbuf std::ios_base::openmode m_mode; CharT * m_buffer; std::size_t m_length; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!A basic_istream class that uses a fixed size character buffer //!as its formatting buffer. template <class CharT, class CharTraits> -class basic_ibufferstream - : public std::basic_istream<CharT, CharTraits> +class basic_ibufferstream : + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private basic_bufferbuf<CharT, CharTraits>, + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public std::basic_istream<CharT, CharTraits> { public: // Typedefs typedef typename std::basic_ios @@ -262,24 +269,40 @@ class basic_ibufferstream typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type; typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type; + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: - typedef std::basic_ios<char_type, CharTraits> basic_ios_t; - typedef std::basic_istream<char_type, CharTraits> base_t; + typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t; + typedef std::basic_ios<char_type, CharTraits> basic_ios_t; + typedef std::basic_istream<char_type, CharTraits> base_t; + bufferbuf_t & get_buf() { return *this; } + const bufferbuf_t & get_buf() const{ return *this; } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. //!Does not throw. basic_ibufferstream(std::ios_base::openmode mode = std::ios_base::in) - : basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::in) - { basic_ios_t::init(&m_buf); } + : //basic_ios_t() is called first (lefting it uninitialized) as it's a + //virtual base of basic_istream. The class will be initialized when + //basic_istream is constructed calling basic_ios_t::init(). + //As bufferbuf_t's constructor does not throw there is no risk of + //calling the basic_ios_t's destructor without calling basic_ios_t::init() + bufferbuf_t(mode | std::ios_base::in) + , base_t(&get_buf()) + {} //!Constructor. Assigns formatting buffer. //!Does not throw. - basic_ibufferstream(const CharT *buffer, std::size_t length, - std::ios_base::openmode mode = std::ios_base::in) - : basic_ios_t(), base_t(0), - m_buf(const_cast<CharT*>(buffer), length, mode | std::ios_base::in) - { basic_ios_t::init(&m_buf); } + basic_ibufferstream(const CharT *buf, std::size_t length, + std::ios_base::openmode mode = std::ios_base::in) + : //basic_ios_t() is called first (lefting it uninitialized) as it's a + //virtual base of basic_istream. The class will be initialized when + //basic_istream is constructed calling basic_ios_t::init(). + //As bufferbuf_t's constructor does not throw there is no risk of + //calling the basic_ios_t's destructor without calling basic_ios_t::init() + bufferbuf_t(const_cast<CharT*>(buf), length, mode | std::ios_base::in) + , base_t(&get_buf()) + {} ~basic_ibufferstream(){}; @@ -287,29 +310,27 @@ class basic_ibufferstream //!Returns the address of the stored //!stream buffer. basic_bufferbuf<CharT, CharTraits>* rdbuf() const - { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); } + { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); } //!Returns the pointer and size of the internal buffer. //!Does not throw. std::pair<const CharT *, std::size_t> buffer() const - { return m_buf.buffer(); } + { return get_buf().buffer(); } //!Sets the underlying buffer to a new value. Resets //!stream position. Does not throw. - void buffer(const CharT *buffer, std::size_t length) - { m_buf.buffer(const_cast<CharT*>(buffer), length); } - - /// @cond - private: - basic_bufferbuf<CharT, CharTraits> m_buf; - /// @endcond + void buffer(const CharT *buf, std::size_t length) + { get_buf().buffer(const_cast<CharT*>(buf), length); } }; //!A basic_ostream class that uses a fixed size character buffer //!as its formatting buffer. template <class CharT, class CharTraits> -class basic_obufferstream - : public std::basic_ostream<CharT, CharTraits> +class basic_obufferstream : + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private basic_bufferbuf<CharT, CharTraits>, + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public std::basic_ostream<CharT, CharTraits> { public: typedef typename std::basic_ios @@ -319,25 +340,40 @@ class basic_obufferstream typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type; typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: + typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t; typedef std::basic_ios<char_type, CharTraits> basic_ios_t; typedef std::basic_ostream<char_type, CharTraits> base_t; - /// @endcond + bufferbuf_t & get_buf() { return *this; } + const bufferbuf_t & get_buf() const{ return *this; } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: //!Constructor. //!Does not throw. basic_obufferstream(std::ios_base::openmode mode = std::ios_base::out) - : basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::out) - { basic_ios_t::init(&m_buf); } + : //basic_ios_t() is called first (lefting it uninitialized) as it's a + //virtual base of basic_istream. The class will be initialized when + //basic_istream is constructed calling basic_ios_t::init(). + //As bufferbuf_t's constructor does not throw there is no risk of + //calling the basic_ios_t's destructor without calling basic_ios_t::init() + bufferbuf_t(mode | std::ios_base::out) + , base_t(&get_buf()) + {} //!Constructor. Assigns formatting buffer. //!Does not throw. - basic_obufferstream(CharT *buffer, std::size_t length, + basic_obufferstream(CharT *buf, std::size_t length, std::ios_base::openmode mode = std::ios_base::out) - : basic_ios_t(), base_t(0), - m_buf(buffer, length, mode | std::ios_base::out) - { basic_ios_t::init(&m_buf); } + : //basic_ios_t() is called first (lefting it uninitialized) as it's a + //virtual base of basic_istream. The class will be initialized when + //basic_istream is constructed calling basic_ios_t::init(). + //As bufferbuf_t's constructor does not throw there is no risk of + //calling the basic_ios_t's destructor without calling basic_ios_t::init() + bufferbuf_t(buf, length, mode | std::ios_base::out) + , base_t(&get_buf()) + {} ~basic_obufferstream(){} @@ -345,31 +381,28 @@ class basic_obufferstream //!Returns the address of the stored //!stream buffer. basic_bufferbuf<CharT, CharTraits>* rdbuf() const - { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); } + { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); } //!Returns the pointer and size of the internal buffer. //!Does not throw. std::pair<CharT *, std::size_t> buffer() const - { return m_buf.buffer(); } + { return get_buf().buffer(); } //!Sets the underlying buffer to a new value. Resets //!stream position. Does not throw. - void buffer(CharT *buffer, std::size_t length) - { m_buf.buffer(buffer, length); } - - /// @cond - private: - basic_bufferbuf<CharT, CharTraits> m_buf; - /// @endcond + void buffer(CharT *buf, std::size_t length) + { get_buf().buffer(buf, length); } }; //!A basic_iostream class that uses a fixed size character buffer //!as its formatting buffer. template <class CharT, class CharTraits> -class basic_bufferstream - : public std::basic_iostream<CharT, CharTraits> - +class basic_bufferstream : + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private basic_bufferbuf<CharT, CharTraits>, + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public std::basic_iostream<CharT, CharTraits> { public: // Typedefs typedef typename std::basic_ios @@ -379,27 +412,42 @@ class basic_bufferstream typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type; typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: - typedef std::basic_ios<char_type, CharTraits> basic_ios_t; - typedef std::basic_iostream<char_type, CharTraits> base_t; - /// @endcond + typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t; + typedef std::basic_ios<char_type, CharTraits> basic_ios_t; + typedef std::basic_iostream<char_type, CharTraits> base_t; + bufferbuf_t & get_buf() { return *this; } + const bufferbuf_t & get_buf() const{ return *this; } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. //!Does not throw. basic_bufferstream(std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) - : basic_ios_t(), base_t(0), m_buf(mode) - { basic_ios_t::init(&m_buf); } + : //basic_ios_t() is called first (lefting it uninitialized) as it's a + //virtual base of basic_istream. The class will be initialized when + //basic_istream is constructed calling basic_ios_t::init(). + //As bufferbuf_t's constructor does not throw there is no risk of + //calling the basic_ios_t's destructor without calling basic_ios_t::init() + bufferbuf_t(mode) + , base_t(&get_buf()) + {} //!Constructor. Assigns formatting buffer. //!Does not throw. - basic_bufferstream(CharT *buffer, std::size_t length, + basic_bufferstream(CharT *buf, std::size_t length, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) - : basic_ios_t(), base_t(0), m_buf(buffer, length, mode) - { basic_ios_t::init(&m_buf); } + : //basic_ios_t() is called first (lefting it uninitialized) as it's a + //virtual base of basic_istream. The class will be initialized when + //basic_istream is constructed calling basic_ios_t::init(). + //As bufferbuf_t's constructor does not throw there is no risk of + //calling the basic_ios_t's destructor without calling basic_ios_t::init() + bufferbuf_t(buf, length, mode) + , base_t(&get_buf()) + {} ~basic_bufferstream(){} @@ -407,22 +455,17 @@ class basic_bufferstream //!Returns the address of the stored //!stream buffer. basic_bufferbuf<CharT, CharTraits>* rdbuf() const - { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); } + { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); } //!Returns the pointer and size of the internal buffer. //!Does not throw. std::pair<CharT *, std::size_t> buffer() const - { return m_buf.buffer(); } + { return get_buf().buffer(); } //!Sets the underlying buffer to a new value. Resets //!stream position. Does not throw. - void buffer(CharT *buffer, std::size_t length) - { m_buf.buffer(buffer, length); } - - /// @cond - private: - basic_bufferbuf<CharT, CharTraits> m_buf; - /// @endcond + void buffer(CharT *buf, std::size_t length) + { get_buf().buffer(buf, length); } }; //Some typedefs to simplify usage diff --git a/boost/interprocess/streams/vectorstream.hpp b/boost/interprocess/streams/vectorstream.hpp index 3cee7200ab..94a75723b6 100644 --- a/boost/interprocess/streams/vectorstream.hpp +++ b/boost/interprocess/streams/vectorstream.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -8,7 +8,7 @@ // ////////////////////////////////////////////////////////////////////////////// // -// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005. +// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012. // Changed internal SGI string to a generic, templatized vector. Added efficient // internal buffer get/set/swap functions, so that we can obtain/establish the // internal buffer without any reallocation or copy. Kill those temporaries! @@ -36,6 +36,10 @@ #ifndef BOOST_INTERPROCESS_VECTORSTREAM_HPP #define BOOST_INTERPROCESS_VECTORSTREAM_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -43,7 +47,7 @@ #include <ios> #include <istream> #include <ostream> -#include <string> // char traits +#include <string> // char traits #include <cstddef> // ptrdiff_t #include <boost/interprocess/interprocess_fwd.hpp> #include <boost/assert.hpp> @@ -67,13 +71,13 @@ class basic_vectorbuf typedef typename CharTraits::off_type off_type; typedef CharTraits traits_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef std::basic_streambuf<char_type, traits_type> base_t; basic_vectorbuf(const basic_vectorbuf&); basic_vectorbuf & operator =(const basic_vectorbuf&); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Throws if vector_type default @@ -92,15 +96,13 @@ class basic_vectorbuf : base_t(), m_mode(mode), m_vect(param) { this->initialize_pointers(); } - virtual ~basic_vectorbuf(){} - public: //!Swaps the underlying vector with the passed vector. //!This function resets the read/write position in the stream. //!Does not throw. void swap_vector(vector_type &vect) - { + { if (this->m_mode & std::ios_base::out){ //Update high water if necessary //And resize vector to remove extra size @@ -119,7 +121,7 @@ class basic_vectorbuf //!Returns a const reference to the internal vector. //!Does not throw. const vector_type &vector() const - { + { if (this->m_mode & std::ios_base::out){ if (mp_high_water < base_t::pptr()){ //Restore the vector's size if necessary @@ -163,7 +165,7 @@ class basic_vectorbuf void clear() { m_vect.clear(); this->initialize_pointers(); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //Maximizes high watermark to the initial vector size, //initializes read and write iostream buffers to the capacity @@ -358,7 +360,7 @@ class basic_vectorbuf std::ios_base::openmode m_mode; mutable vector_type m_vect; mutable char_type* mp_high_water; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!A basic_istream class that holds a character vector specified by CharVector @@ -367,10 +369,10 @@ class basic_vectorbuf //!boost::interprocess::basic_string template <class CharVector, class CharTraits> class basic_ivectorstream - /// @cond - : private basic_vectorbuf<CharVector, CharTraits> - /// @endcond - , public std::basic_istream<typename CharVector::value_type, CharTraits> + : public std::basic_istream<typename CharVector::value_type, CharTraits> + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + , private basic_vectorbuf<CharVector, CharTraits> + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { public: typedef CharVector vector_type; @@ -381,59 +383,65 @@ class basic_ivectorstream typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type; typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef basic_vectorbuf<CharVector, CharTraits> vectorbuf_t; + typedef std::basic_ios<char_type, CharTraits> basic_ios_t; typedef std::basic_istream<char_type, CharTraits> base_t; - vectorbuf_t & m_buf() { return *this; } - const vectorbuf_t & m_buf() const{ return *this; } - /// @endcond + vectorbuf_t & get_buf() { return *this; } + const vectorbuf_t & get_buf() const{ return *this; } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: + //!Constructor. Throws if vector_type default //!constructor throws. basic_ivectorstream(std::ios_base::openmode mode = std::ios_base::in) - : vectorbuf_t(mode | std::ios_base::in), base_t(&m_buf()) - {} + : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base + //(via basic_ios::init() call in base_t's constructor) without the risk of a + //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. + , vectorbuf_t(mode | std::ios_base::in) + { this->base_t::rdbuf(&get_buf()); } //!Constructor. Throws if vector_type(const VectorParameter ¶m) //!throws. template<class VectorParameter> basic_ivectorstream(const VectorParameter ¶m, std::ios_base::openmode mode = std::ios_base::in) - : vectorbuf_t(param, mode | std::ios_base::in), base_t(&m_buf()) + : vectorbuf_t(param, mode | std::ios_base::in) + //basic_ios_t() is constructed uninitialized as virtual base + //and initialized inside base_t calling basic_ios::init() + , base_t(&get_buf()) {} - ~basic_ivectorstream(){}; - public: //!Returns the address of the stored //!stream buffer. basic_vectorbuf<CharVector, CharTraits>* rdbuf() const - { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf()); } + { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); } //!Swaps the underlying vector with the passed vector. //!This function resets the read position in the stream. //!Does not throw. void swap_vector(vector_type &vect) - { m_buf().swap_vector(vect); } + { get_buf().swap_vector(vect); } //!Returns a const reference to the internal vector. //!Does not throw. const vector_type &vector() const - { return m_buf().vector(); } + { return get_buf().vector(); } //!Calls reserve() method of the internal vector. //!Resets the stream to the first position. //!Throws if the internals vector's reserve throws. void reserve(typename vector_type::size_type size) - { m_buf().reserve(size); } + { get_buf().reserve(size); } //!Calls clear() method of the internal vector. //!Resets the stream to the first position. void clear() - { m_buf().clear(); } + { get_buf().clear(); } }; //!A basic_ostream class that holds a character vector specified by CharVector @@ -442,10 +450,10 @@ class basic_ivectorstream //!boost::interprocess::basic_string template <class CharVector, class CharTraits> class basic_ovectorstream - /// @cond - : private basic_vectorbuf<CharVector, CharTraits> - /// @endcond - , public std::basic_ostream<typename CharVector::value_type, CharTraits> + : public std::basic_ostream<typename CharVector::value_type, CharTraits> + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + , private basic_vectorbuf<CharVector, CharTraits> + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { public: typedef CharVector vector_type; @@ -456,57 +464,61 @@ class basic_ovectorstream typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type; typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef basic_vectorbuf<CharVector, CharTraits> vectorbuf_t; + typedef std::basic_ios<char_type, CharTraits> basic_ios_t; typedef std::basic_ostream<char_type, CharTraits> base_t; - vectorbuf_t & m_buf() { return *this; } - const vectorbuf_t & m_buf()const { return *this; } - /// @endcond + vectorbuf_t & get_buf() { return *this; } + const vectorbuf_t & get_buf()const { return *this; } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Throws if vector_type default //!constructor throws. basic_ovectorstream(std::ios_base::openmode mode = std::ios_base::out) - : vectorbuf_t(mode | std::ios_base::out), base_t(&m_buf()) - {} + : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base + //(via basic_ios::init() call in base_t's constructor) without the risk of a + //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. + , vectorbuf_t(mode | std::ios_base::out) + { this->base_t::rdbuf(&get_buf()); } //!Constructor. Throws if vector_type(const VectorParameter ¶m) //!throws. template<class VectorParameter> basic_ovectorstream(const VectorParameter ¶m, std::ios_base::openmode mode = std::ios_base::out) - : vectorbuf_t(param, mode | std::ios_base::out), base_t(&m_buf()) - {} - - ~basic_ovectorstream(){} + : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base + //(via basic_ios::init() call in base_t's constructor) without the risk of a + //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. + , vectorbuf_t(param, mode | std::ios_base::out) + { this->base_t::rdbuf(&get_buf()); } public: //!Returns the address of the stored //!stream buffer. basic_vectorbuf<CharVector, CharTraits>* rdbuf() const - { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf()); } + { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); } //!Swaps the underlying vector with the passed vector. //!This function resets the write position in the stream. //!Does not throw. void swap_vector(vector_type &vect) - { m_buf().swap_vector(vect); } + { get_buf().swap_vector(vect); } //!Returns a const reference to the internal vector. //!Does not throw. const vector_type &vector() const - { return m_buf().vector(); } + { return get_buf().vector(); } //!Calls reserve() method of the internal vector. //!Resets the stream to the first position. //!Throws if the internals vector's reserve throws. void reserve(typename vector_type::size_type size) - { m_buf().reserve(size); } + { get_buf().reserve(size); } }; - //!A basic_iostream class that holds a character vector specified by CharVector //!template parameter as its formatting buffer. The vector must have //!contiguous storage, like std::vector, boost::interprocess::vector or @@ -514,7 +526,9 @@ class basic_ovectorstream template <class CharVector, class CharTraits> class basic_vectorstream : public std::basic_iostream<typename CharVector::value_type, CharTraits> - + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + , private basic_vectorbuf<CharVector, CharTraits> + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { public: typedef CharVector vector_type; @@ -525,61 +539,64 @@ class basic_vectorstream typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type; typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: - typedef std::basic_ios<char_type, CharTraits> basic_ios_t; - typedef std::basic_iostream<char_type, CharTraits> base_t; - /// @endcond + typedef basic_vectorbuf<CharVector, CharTraits> vectorbuf_t; + typedef std::basic_ios<char_type, CharTraits> basic_ios_t; + typedef std::basic_iostream<char_type, CharTraits> base_t; + + vectorbuf_t & get_buf() { return *this; } + const vectorbuf_t & get_buf() const{ return *this; } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Throws if vector_type default //!constructor throws. basic_vectorstream(std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) - : basic_ios_t(), base_t(0), m_buf(mode) - { basic_ios_t::init(&m_buf); } + : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base + //(via basic_ios::init() call in base_t's constructor) without the risk of a + //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. + , vectorbuf_t(mode) + { this->base_t::rdbuf(&get_buf()); } //!Constructor. Throws if vector_type(const VectorParameter ¶m) //!throws. template<class VectorParameter> basic_vectorstream(const VectorParameter ¶m, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) - : basic_ios_t(), base_t(0), m_buf(param, mode) - { basic_ios_t::init(&m_buf); } - - ~basic_vectorstream(){} + : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base + //(via basic_ios::init() call in base_t's constructor) without the risk of a + //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. + , vectorbuf_t(param, mode) + { this->base_t::rdbuf(&get_buf()); } public: //Returns the address of the stored stream buffer. basic_vectorbuf<CharVector, CharTraits>* rdbuf() const - { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf); } + { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); } //!Swaps the underlying vector with the passed vector. //!This function resets the read/write position in the stream. //!Does not throw. void swap_vector(vector_type &vect) - { m_buf.swap_vector(vect); } + { get_buf().swap_vector(vect); } //!Returns a const reference to the internal vector. //!Does not throw. const vector_type &vector() const - { return m_buf.vector(); } + { return get_buf().vector(); } //!Calls reserve() method of the internal vector. //!Resets the stream to the first position. //!Throws if the internals vector's reserve throws. void reserve(typename vector_type::size_type size) - { m_buf.reserve(size); } + { get_buf().reserve(size); } //!Calls clear() method of the internal vector. //!Resets the stream to the first position. void clear() - { m_buf.clear(); } - - /// @cond - private: - basic_vectorbuf<CharVector, CharTraits> m_buf; - /// @endcond + { get_buf().clear(); } }; //Some typedefs to simplify usage diff --git a/boost/interprocess/sync/detail/common_algorithms.hpp b/boost/interprocess/sync/detail/common_algorithms.hpp new file mode 100644 index 0000000000..76d1c5c9e8 --- /dev/null +++ b/boost/interprocess/sync/detail/common_algorithms.hpp @@ -0,0 +1,77 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2013. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SYNC_DETAIL_COMMON_ALGORITHMS_HPP +#define BOOST_INTERPROCESS_SYNC_DETAIL_COMMON_ALGORITHMS_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> + +#include <boost/interprocess/sync/spin/wait.hpp> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +template<class MutexType> +bool try_based_timed_lock(MutexType &m, const boost::posix_time::ptime &abs_time) +{ + //Same as lock() + if(abs_time == boost::posix_time::pos_infin){ + m.lock(); + return true; + } + //Always try to lock to achieve POSIX guarantees: + // "Under no circumstance shall the function fail with a timeout if the mutex + // can be locked immediately. The validity of the abs_timeout parameter need not + // be checked if the mutex can be locked immediately." + else if(m.try_lock()){ + return true; + } + else{ + spin_wait swait; + while(microsec_clock::universal_time() < abs_time){ + if(m.try_lock()){ + return true; + } + swait.yield(); + } + return false; + } +} + +template<class MutexType> +void try_based_lock(MutexType &m) +{ + if(!m.try_lock()){ + spin_wait swait; + do{ + if(m.try_lock()){ + break; + } + else{ + swait.yield(); + } + } + while(1); + } +} + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_SYNC_DETAIL_COMMON_ALGORITHMS_HPP diff --git a/boost/interprocess/sync/detail/condition_algorithm_8a.hpp b/boost/interprocess/sync/detail/condition_algorithm_8a.hpp index eaad671cdf..be93af7b8f 100644 --- a/boost/interprocess/sync/detail/condition_algorithm_8a.hpp +++ b/boost/interprocess/sync/detail/condition_algorithm_8a.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,9 +11,14 @@ #ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP #define BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> +#include <boost/interprocess/sync/detail/locks.hpp> #include <limits> namespace boost { @@ -161,6 +166,15 @@ namespace ipcdetail { // mutex_type &get_mtx_unblock_lock() // }; // +// Must be initialized as following +// +// get_nwaiters_blocked() == 0 +// get_nwaiters_gone() == 0 +// get_nwaiters_to_unblock() == 0 +// get_sem_block_queue() == initial count 0 +// get_sem_block_lock() == initial count 1 +// get_mtx_unblock_lock() (unlocked) +// template<class ConditionMembers> class condition_algorithm_8a { @@ -174,16 +188,10 @@ class condition_algorithm_8a typedef typename ConditionMembers::mutex_type mutex_type; typedef typename ConditionMembers::integer_type integer_type; - // nwaiters_blocked == 0 - // nwaiters_gone() == 0 - // nwaiters_to_unblock == 0 - // sem_block_queue() == initial count 0 - // sem_block_lock() == initial count 1 - // mtx_unblock_lock (unlocked) - public: - template<class InterprocessMutex> - static bool wait (ConditionMembers &data, bool timeout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut); + template<class Lock> + static bool wait ( ConditionMembers &data, Lock &lock + , bool timeout_enabled, const boost::posix_time::ptime &abs_time); static void signal(ConditionMembers &data, bool broadcast); }; @@ -235,9 +243,13 @@ inline void condition_algorithm_8a<ConditionMembers>::signal(ConditionMembers &d } template<class ConditionMembers> -template<class InterprocessMutex> +template<class Lock> inline bool condition_algorithm_8a<ConditionMembers>::wait - (ConditionMembers &data, bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mtxExternal) + ( ConditionMembers &data + , Lock &lock + , bool tout_enabled + , const boost::posix_time::ptime &abs_time + ) { //Initialize to avoid warnings integer_type nsignals_was_left = 0; @@ -247,19 +259,13 @@ inline bool condition_algorithm_8a<ConditionMembers>::wait ++data.get_nwaiters_blocked(); data.get_sem_block_lock().post(); - struct scoped_unlock - { - InterprocessMutex & mut; - scoped_unlock(InterprocessMutex & m) - : mut(m) - { m.unlock(); } + //Unlock external lock and program for relock + lock_inverter<Lock> inverted_lock(lock); + scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock); - ~scoped_unlock() - { mut.lock(); } - } unlocker(mtxExternal); - - - bool bTimedOut = tout_enabled ? !data.get_sem_block_queue().timed_wait(abs_time) : (data.get_sem_block_queue().wait(), false); + bool bTimedOut = tout_enabled + ? !data.get_sem_block_queue().timed_wait(abs_time) + : (data.get_sem_block_queue().wait(), false); { scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock()); @@ -290,7 +296,7 @@ inline bool condition_algorithm_8a<ConditionMembers>::wait data.get_nwaiters_gone() = 0; } //locker's destructor triggers data.get_mtx_unblock_lock().unlock() - } + } if ( 1 == nsignals_was_left ) { if ( 0 != nwaiters_was_gone ) { @@ -302,11 +308,80 @@ inline bool condition_algorithm_8a<ConditionMembers>::wait data.get_sem_block_lock().post(); // open the gate } - //mtxExternal.lock(); called from unlocker + //lock.lock(); called from unlocker destructor return ( bTimedOut ) ? false : true; } + +template<class ConditionMembers> +class condition_8a_wrapper +{ + //Non-copyable + condition_8a_wrapper(const condition_8a_wrapper &); + condition_8a_wrapper &operator=(const condition_8a_wrapper &); + + ConditionMembers m_data; + typedef ipcdetail::condition_algorithm_8a<ConditionMembers> algo_type; + + public: + + condition_8a_wrapper(){} + + //Compiler-generated destructor is OK + //~condition_8a_wrapper(){} + + ConditionMembers & get_members() + { return m_data; } + + const ConditionMembers & get_members() const + { return m_data; } + + void notify_one() + { algo_type::signal(m_data, false); } + + void notify_all() + { algo_type::signal(m_data, true); } + + template <typename L> + void wait(L& lock) + { + if (!lock) + throw lock_exception(); + algo_type::wait(m_data, lock, false, boost::posix_time::ptime()); + } + + template <typename L, typename Pr> + void wait(L& lock, Pr pred) + { + if (!lock) + throw lock_exception(); + + while (!pred()) + algo_type::wait(m_data, lock, false, boost::posix_time::ptime()); + } + + template <typename L> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { + if (!lock) + throw lock_exception(); + return algo_type::wait(m_data, lock, true, abs_time); + } + + template <typename L, typename Pr> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { + if (!lock) + throw lock_exception(); + while (!pred()){ + if (!algo_type::wait(m_data, lock, true, abs_time)) + return pred(); + } + return true; + } +}; + } //namespace ipcdetail } //namespace interprocess } //namespace boost diff --git a/boost/interprocess/sync/detail/condition_any_algorithm.hpp b/boost/interprocess/sync/detail/condition_any_algorithm.hpp new file mode 100644 index 0000000000..5819acfa28 --- /dev/null +++ b/boost/interprocess/sync/detail/condition_any_algorithm.hpp @@ -0,0 +1,220 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP +#define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/sync/scoped_lock.hpp> +#include <boost/interprocess/sync/detail/locks.hpp> +#include <limits> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// +// Condition variable 'any' (able to use any type of external mutex) +// +// The code is based on Howard E. Hinnant's ISO C++ N2406 paper. +// Many thanks to Howard for his support and comments. +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +// Required interface for ConditionAnyMembers +// class ConditionAnyMembers +// { +// typedef implementation_defined mutex_type; +// typedef implementation_defined condvar_type; +// +// condvar &get_condvar() +// mutex_type &get_mutex() +// }; +// +// Must be initialized as following +// +// get_condvar() [no threads blocked] +// get_mutex() [unlocked] + +template<class ConditionAnyMembers> +class condition_any_algorithm +{ + private: + condition_any_algorithm(); + ~condition_any_algorithm(); + condition_any_algorithm(const condition_any_algorithm &); + condition_any_algorithm &operator=(const condition_any_algorithm &); + + typedef typename ConditionAnyMembers::mutex_type mutex_type; + typedef typename ConditionAnyMembers::condvar_type condvar_type; + + template <class Lock> + static void do_wait(ConditionAnyMembers &data, Lock& lock); + + template <class Lock> + static bool do_timed_wait(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time); + + public: + template<class Lock> + static bool wait ( ConditionAnyMembers &data, Lock &mut + , bool timeout_enabled, const boost::posix_time::ptime &abs_time); + static void signal( ConditionAnyMembers &data, bool broadcast); +}; + +template<class ConditionAnyMembers> +void condition_any_algorithm<ConditionAnyMembers>::signal(ConditionAnyMembers &data, bool broadcast) +{ + scoped_lock<mutex_type> internal_lock(data.get_mutex()); + if(broadcast){ + data.get_condvar().notify_all(); + } + else{ + data.get_condvar().notify_one(); + } +} + +template<class ConditionAnyMembers> +template<class Lock> +bool condition_any_algorithm<ConditionAnyMembers>::wait + ( ConditionAnyMembers &data + , Lock &lock + , bool tout_enabled + , const boost::posix_time::ptime &abs_time) +{ + if(tout_enabled){ + return condition_any_algorithm::do_timed_wait(data, lock, abs_time); + } + else{ + condition_any_algorithm::do_wait(data, lock); + return true; + } +} + +template<class ConditionAnyMembers> +template <class Lock> +void condition_any_algorithm<ConditionAnyMembers>::do_wait + (ConditionAnyMembers &data, Lock& lock) +{ + //lock internal before unlocking external to avoid race with a notifier + scoped_lock<mutex_type> internal_lock(data.get_mutex()); + { + lock_inverter<Lock> inverted_lock(lock); + scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock); + { //unlock internal first to avoid deadlock with near simultaneous waits + scoped_lock<mutex_type> internal_unlock; + internal_lock.swap(internal_unlock); + data.get_condvar().wait(internal_unlock); + } + } +} + +template<class ConditionAnyMembers> +template <class Lock> +bool condition_any_algorithm<ConditionAnyMembers>::do_timed_wait + (ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time) +{ + //lock internal before unlocking external to avoid race with a notifier + scoped_lock<mutex_type> internal_lock(data.get_mutex()); + { + //Unlock external lock and program for relock + lock_inverter<Lock> inverted_lock(lock); + scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock); + { //unlock internal first to avoid deadlock with near simultaneous waits + scoped_lock<mutex_type> internal_unlock; + internal_lock.swap(internal_unlock); + return data.get_condvar().timed_wait(internal_unlock, abs_time); + } + } +} + + +template<class ConditionAnyMembers> +class condition_any_wrapper +{ + //Non-copyable + condition_any_wrapper(const condition_any_wrapper &); + condition_any_wrapper &operator=(const condition_any_wrapper &); + + ConditionAnyMembers m_data; + typedef ipcdetail::condition_any_algorithm<ConditionAnyMembers> algo_type; + + public: + + condition_any_wrapper(){} + + ~condition_any_wrapper(){} + + ConditionAnyMembers & get_members() + { return m_data; } + + const ConditionAnyMembers & get_members() const + { return m_data; } + + void notify_one() + { algo_type::signal(m_data, false); } + + void notify_all() + { algo_type::signal(m_data, true); } + + template <typename L> + void wait(L& lock) + { + if (!lock) + throw lock_exception(); + algo_type::wait(m_data, lock, false, boost::posix_time::ptime()); + } + + template <typename L, typename Pr> + void wait(L& lock, Pr pred) + { + if (!lock) + throw lock_exception(); + + while (!pred()) + algo_type::wait(m_data, lock, false, boost::posix_time::ptime()); + } + + template <typename L> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { + if (!lock) + throw lock_exception(); + return algo_type::wait(m_data, lock, true, abs_time); + } + + template <typename L, typename Pr> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { + if (!lock) + throw lock_exception(); + while (!pred()){ + if (!algo_type::wait(m_data, lock, true, abs_time)) + return pred(); + } + return true; + } +}; + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP diff --git a/boost/interprocess/sync/detail/locks.hpp b/boost/interprocess/sync/detail/locks.hpp new file mode 100644 index 0000000000..05652003a8 --- /dev/null +++ b/boost/interprocess/sync/detail/locks.hpp @@ -0,0 +1,97 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_LOCKS_HPP +#define BOOST_INTERPROCESS_DETAIL_LOCKS_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +template<class Lock> +class internal_mutex_lock +{ + typedef void (internal_mutex_lock::*unspecified_bool_type)(); + public: + + typedef typename Lock::mutex_type::internal_mutex_type mutex_type; + + + internal_mutex_lock(Lock &l) + : l_(l) + {} + + mutex_type* mutex() const + { return l_ ? &l_.mutex()->internal_mutex() : 0; } + + void lock() { l_.lock(); } + + void unlock() { l_.unlock(); } + + operator unspecified_bool_type() const + { return l_ ? &internal_mutex_lock::lock : 0; } + + private: + Lock &l_; +}; + +template <class Lock> +class lock_inverter +{ + Lock &l_; + public: + lock_inverter(Lock &l) + : l_(l) + {} + void lock() { l_.unlock(); } + void unlock() { l_.lock(); } +}; + +template <class Lock> +class lock_to_sharable +{ + Lock &l_; + + public: + explicit lock_to_sharable(Lock &l) + : l_(l) + {} + void lock() { l_.lock_sharable(); } + bool try_lock(){ return l_.try_lock_sharable(); } + void unlock() { l_.unlock_sharable(); } +}; + +template <class Lock> +class lock_to_wait +{ + Lock &l_; + + public: + explicit lock_to_wait(Lock &l) + : l_(l) + {} + void lock() { l_.wait(); } + bool try_lock(){ return l_.try_wait(); } +}; + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_DETAIL_LOCKS_HPP diff --git a/boost/interprocess/sync/file_lock.hpp b/boost/interprocess/sync/file_lock.hpp index e0f75465fb..e8d3903dbe 100644 --- a/boost/interprocess/sync/file_lock.hpp +++ b/boost/interprocess/sync/file_lock.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_FILE_LOCK_HPP #define BOOST_INTERPROCESS_FILE_LOCK_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -21,7 +21,9 @@ #include <boost/interprocess/detail/os_file_functions.hpp> #include <boost/interprocess/detail/os_thread_functions.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> -#include <boost/move/move.hpp> +#include <boost/interprocess/sync/detail/common_algorithms.hpp> +#include <boost/interprocess/sync/detail/locks.hpp> +#include <boost/move/utility_core.hpp> //!\file //!Describes a class that wraps file locking capabilities. @@ -37,10 +39,10 @@ namespace interprocess { //!process so just use file locks to synchronize threads from different processes. class file_lock { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable BOOST_MOVABLE_BUT_NOT_COPYABLE(file_lock) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructs an empty file mapping. @@ -64,10 +66,10 @@ class file_lock //!After the call, "moved" does not represent any file mapping. //!Does not throw file_lock &operator=(BOOST_RV_REF(file_lock) moved) - { + { file_lock tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Closes a file lock. Does not throw. @@ -81,7 +83,7 @@ class file_lock m_file_hnd = other.m_file_hnd; other.m_file_hnd = tmp; } - + //Exclusive locking //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, @@ -137,66 +139,11 @@ class file_lock //!Effects: The calling thread releases the sharable ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock_sharable(); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: file_handle_t m_file_hnd; - bool timed_acquire_file_lock - (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time) - { - //Obtain current count and target time - boost::posix_time::ptime now = microsec_clock::universal_time(); - using namespace boost::detail; - - if(now >= abs_time) return false; - - do{ - if(!ipcdetail::try_acquire_file_lock(hnd, acquired)) - return false; - - if(acquired) - return true; - else{ - now = microsec_clock::universal_time(); - - if(now >= abs_time){ - acquired = false; - return true; - } - // relinquish current time slice - ipcdetail::thread_yield(); - } - }while (true); - } - - bool timed_acquire_file_lock_sharable - (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time) - { - //Obtain current count and target time - boost::posix_time::ptime now = microsec_clock::universal_time(); - using namespace boost::detail; - - if(now >= abs_time) return false; - - do{ - if(!ipcdetail::try_acquire_file_lock_sharable(hnd, acquired)) - return false; - - if(acquired) - return true; - else{ - now = microsec_clock::universal_time(); - - if(now >= abs_time){ - acquired = false; - return true; - } - // relinquish current time slice - ipcdetail::thread_yield(); - } - }while (true); - } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; inline file_lock::file_lock(const char *name) @@ -236,18 +183,7 @@ inline bool file_lock::try_lock() } inline bool file_lock::timed_lock(const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - bool result; - if(!this->timed_acquire_file_lock(m_file_hnd, result, abs_time)){ - error_info err(system_error_code()); - throw interprocess_exception(err); - } - return result; -} +{ return ipcdetail::try_based_timed_lock(*this, abs_time); } inline void file_lock::unlock() { @@ -277,16 +213,8 @@ inline bool file_lock::try_lock_sharable() inline bool file_lock::timed_lock_sharable(const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->lock_sharable(); - return true; - } - bool result; - if(!this->timed_acquire_file_lock_sharable(m_file_hnd, result, abs_time)){ - error_info err(system_error_code()); - throw interprocess_exception(err); - } - return result; + ipcdetail::lock_to_sharable<file_lock> lsh(*this); + return ipcdetail::try_based_timed_lock(lsh, abs_time); } inline void file_lock::unlock_sharable() diff --git a/boost/interprocess/sync/interprocess_condition.hpp b/boost/interprocess/sync/interprocess_condition.hpp index 9d0bea640e..19fba30762 100644 --- a/boost/interprocess/sync/interprocess_condition.hpp +++ b/boost/interprocess/sync/interprocess_condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,17 +11,18 @@ #ifndef BOOST_INTERPROCESS_CONDITION_HPP #define BOOST_INTERPROCESS_CONDITION_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> #include <boost/interprocess/sync/interprocess_mutex.hpp> +#include <boost/interprocess/sync/detail/locks.hpp> #include <boost/interprocess/exceptions.hpp> #include <boost/limits.hpp> #include <boost/assert.hpp> @@ -38,37 +39,49 @@ #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION #endif -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!\file //!Describes process-shared variables interprocess_condition class namespace boost { +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + namespace posix_time { class ptime; } +#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + namespace interprocess { class named_condition; //!This class is a condition variable that can be placed in shared memory or //!memory mapped files. +//!Destroys the object of type std::condition_variable_any +//! +//!Unlike std::condition_variable in C++11, it is NOT safe to invoke the destructor if all +//!threads have been only notified. It is required that they have exited their respective wait +//!functions. class interprocess_condition { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable interprocess_condition(const interprocess_condition &); interprocess_condition &operator=(const interprocess_condition &); friend class named_condition; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: //!Constructs a interprocess_condition. On error throws interprocess_exception. - interprocess_condition(){} + interprocess_condition() + {} //!Destroys *this //!liberating system resources. - ~interprocess_condition(){} + ~interprocess_condition() + {} //!If there is a thread waiting on *this, change that //!thread's state to ready. Otherwise there is no effect. @@ -86,9 +99,8 @@ class interprocess_condition template <typename L> void wait(L& lock) { - if (!lock) - throw lock_exception(); - this->do_wait(*lock.mutex()); + ipcdetail::internal_mutex_lock<L> internal_lock(lock); + m_condition.wait(internal_lock); } //!The same as: @@ -96,11 +108,8 @@ class interprocess_condition template <typename L, typename Pr> void wait(L& lock, Pr pred) { - if (!lock) - throw lock_exception(); - - while (!pred()) - this->do_wait(*lock.mutex()); + ipcdetail::internal_mutex_lock<L> internal_lock(lock); + m_condition.wait(internal_lock, pred); } //!Releases the lock on the interprocess_mutex object associated with lock, blocks @@ -111,13 +120,8 @@ class interprocess_condition template <typename L> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock); - return true; - } - if (!lock) - throw lock_exception(); - return this->do_timed_wait(abs_time, *lock.mutex()); + ipcdetail::internal_mutex_lock<L> internal_lock(lock); + return m_condition.timed_wait(internal_lock, abs_time); } //!The same as: while (!pred()) { @@ -126,27 +130,11 @@ class interprocess_condition template <typename L, typename Pr> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) { - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock, pred); - return true; - } - if (!lock) - throw lock_exception(); - while (!pred()){ - if (!this->do_timed_wait(abs_time, *lock.mutex())) - return pred(); - } - - return true; + ipcdetail::internal_mutex_lock<L> internal_lock(lock); + return m_condition.timed_wait(internal_lock, abs_time, pred); } - /// @cond - - void do_wait(interprocess_mutex &mut) - { m_condition.do_wait(mut.mutex); } - - bool do_timed_wait(const boost::posix_time::ptime &abs_time, interprocess_mutex &mut) - { return m_condition.do_timed_wait(abs_time, mut.mutex); } + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: #if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION) @@ -161,7 +149,7 @@ class interprocess_condition #else #error "Unknown platform for interprocess_mutex" #endif - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; } //namespace interprocess diff --git a/boost/interprocess/sync/interprocess_condition_any.hpp b/boost/interprocess/sync/interprocess_condition_any.hpp new file mode 100644 index 0000000000..093d69cda2 --- /dev/null +++ b/boost/interprocess/sync/interprocess_condition_any.hpp @@ -0,0 +1,133 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_CONDITION_ANY_HPP +#define BOOST_INTERPROCESS_CONDITION_ANY_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> + +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/interprocess_mutex.hpp> +#include <boost/interprocess/sync/interprocess_condition.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <boost/interprocess/sync/detail/condition_any_algorithm.hpp> + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!\file +//!Describes process-shared variables interprocess_condition_any class + +namespace boost { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace posix_time +{ class ptime; } + +#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace interprocess { + +//!This class is a condition variable that can be placed in shared memory or +//!memory mapped files. +//! +//!The interprocess_condition_any class is a generalization of interprocess_condition. +//!Whereas interprocess_condition works only on Locks with mutex_type == interprocess_mutex +//!interprocess_condition_any can operate on any user-defined lock that meets the BasicLockable +//!requirements (lock()/unlock() member functions). +//! +//!Unlike std::condition_variable_any in C++11, it is NOT safe to invoke the destructor if all +//!threads have been only notified. It is required that they have exited their respective wait +//!functions. +class interprocess_condition_any +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + interprocess_condition_any(const interprocess_condition_any &); + interprocess_condition_any &operator=(const interprocess_condition_any &); + + class members + { + public: + typedef interprocess_condition condvar_type; + typedef interprocess_mutex mutex_type; + + condvar_type &get_condvar() { return m_cond; } + mutex_type &get_mutex() { return m_mut; } + + private: + condvar_type m_cond; + mutex_type m_mut; + }; + + ipcdetail::condition_any_wrapper<members> m_cond; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + //!Constructs a interprocess_condition_any. On error throws interprocess_exception. + interprocess_condition_any(){} + + //!Destroys *this + //!liberating system resources. + ~interprocess_condition_any(){} + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect. + void notify_one() + { m_cond.notify_one(); } + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all() + { m_cond.notify_all(); } + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template <typename L> + void wait(L& lock) + { m_cond.wait(lock); } + + //!The same as: + //!while (!pred()) wait(lock) + template <typename L, typename Pr> + void wait(L& lock, Pr pred) + { m_cond.wait(lock, pred); } + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!and then reacquires the lock. + //!Returns: false if time abs_time is reached, otherwise true. + template <typename L> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { return m_cond.timed_wait(lock, abs_time); } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template <typename L, typename Pr> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { return m_cond.timed_wait(lock, abs_time, pred); } +}; + +} //namespace interprocess +} // namespace boost + +#include <boost/interprocess/detail/config_end.hpp> + +#endif // BOOST_INTERPROCESS_CONDITION_ANY_HPP diff --git a/boost/interprocess/sync/interprocess_mutex.hpp b/boost/interprocess/sync/interprocess_mutex.hpp index 8110c8472b..f4f7258ad8 100644 --- a/boost/interprocess/sync/interprocess_mutex.hpp +++ b/boost/interprocess/sync/interprocess_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -15,9 +15,9 @@ #ifndef BOOST_INTERPROCESS_MUTEX_HPP #define BOOST_INTERPROCESS_MUTEX_HPP -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -50,7 +50,7 @@ class mutex_traits; #endif -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!\file //!Describes a mutex class that can be placed in memory shared by @@ -65,12 +65,31 @@ class interprocess_condition; //!shared between processes. Allows timed lock tries class interprocess_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable interprocess_mutex(const interprocess_mutex &); interprocess_mutex &operator=(const interprocess_mutex &); friend class interprocess_condition; - /// @endcond + + public: + #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) + #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION + typedef ipcdetail::spin_mutex internal_mutex_type; + private: + friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_mutex>; + void take_ownership(){ m_mutex.take_ownership(); } + public: + #elif defined(BOOST_INTERPROCESS_USE_POSIX) + #undef BOOST_INTERPROCESS_USE_POSIX + typedef ipcdetail::posix_mutex internal_mutex_type; + #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) + #undef BOOST_INTERPROCESS_USE_WINDOWS + typedef ipcdetail::windows_mutex internal_mutex_type; + #else + #error "Unknown platform for interprocess_mutex" + #endif + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. @@ -107,24 +126,17 @@ class interprocess_mutex //!Effects: The calling thread releases the exclusive ownership of the mutex. //!Throws: interprocess_exception on error. void unlock(); - /// @cond - private: - #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) - #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION - friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_mutex>; - void take_ownership(){ mutex.take_ownership(); } - ipcdetail::spin_mutex mutex; - #elif defined(BOOST_INTERPROCESS_USE_POSIX) - #undef BOOST_INTERPROCESS_USE_POSIX - ipcdetail::posix_mutex mutex; - #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) - #undef BOOST_INTERPROCESS_USE_WINDOWS - ipcdetail::windows_mutex mutex; - #else - #error "Unknown platform for interprocess_mutex" - #endif - /// @endcond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + internal_mutex_type &internal_mutex() + { return m_mutex; } + + const internal_mutex_type &internal_mutex() const + { return m_mutex; } + + private: + internal_mutex_type m_mutex; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; } //namespace interprocess { @@ -144,23 +156,25 @@ inline void interprocess_mutex::lock() boost::posix_time::ptime wait_time = boost::posix_time::microsec_clock::universal_time() + boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS); - if (!mutex.timed_lock(wait_time)) + if (!m_mutex.timed_lock(wait_time)) { - throw interprocess_exception(timeout_when_locking_error, "Interprocess mutex timeout when locking. Possible deadlock: owner died without unlocking?"); + throw interprocess_exception(timeout_when_locking_error + , "Interprocess mutex timeout when locking. Possible deadlock: " + "owner died without unlocking?"); } #else - mutex.lock(); + m_mutex.lock(); #endif } inline bool interprocess_mutex::try_lock() -{ return mutex.try_lock(); } +{ return m_mutex.try_lock(); } inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time) -{ return mutex.timed_lock(abs_time); } +{ return m_mutex.timed_lock(abs_time); } inline void interprocess_mutex::unlock() -{ mutex.unlock(); } +{ m_mutex.unlock(); } } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/sync/interprocess_recursive_mutex.hpp b/boost/interprocess/sync/interprocess_recursive_mutex.hpp index 3079108645..fcc0e97228 100644 --- a/boost/interprocess/sync/interprocess_recursive_mutex.hpp +++ b/boost/interprocess/sync/interprocess_recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -27,9 +27,9 @@ #ifndef BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP #define BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -64,7 +64,7 @@ class mutex_traits; #endif -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!\file //!Describes interprocess_recursive_mutex and shared_recursive_try_mutex classes @@ -77,11 +77,11 @@ namespace interprocess { //!process. Allows timed lock tries class interprocess_recursive_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable interprocess_recursive_mutex(const interprocess_recursive_mutex &); interprocess_recursive_mutex &operator=(const interprocess_recursive_mutex &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. //!Throws interprocess_exception on error. @@ -116,7 +116,7 @@ class interprocess_recursive_mutex //! same number of times it is locked. //!Throws: interprocess_exception on error. void unlock(); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: #if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION) @@ -133,7 +133,7 @@ class interprocess_recursive_mutex #else #error "Unknown platform for interprocess_mutex" #endif - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; } //namespace interprocess { diff --git a/boost/interprocess/sync/interprocess_semaphore.hpp b/boost/interprocess/sync/interprocess_semaphore.hpp index 2a2f34fdcf..df65193ceb 100644 --- a/boost/interprocess/sync/interprocess_semaphore.hpp +++ b/boost/interprocess/sync/interprocess_semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,9 +11,9 @@ #ifndef BOOST_INTERPROCESS_SEMAPHORE_HPP #define BOOST_INTERPROCESS_SEMAPHORE_HPP -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -37,7 +37,7 @@ #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION #endif -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!\file //!Describes a interprocess_semaphore class for inter-process synchronization @@ -49,11 +49,11 @@ namespace interprocess { //!shared between processes. Allows timed lock tries class interprocess_semaphore { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable interprocess_semaphore(const interprocess_semaphore &); interprocess_semaphore &operator=(const interprocess_semaphore &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Creates a interprocess_semaphore with the given initial count. //!interprocess_exception if there is an error.*/ @@ -87,7 +87,7 @@ class interprocess_semaphore //!Returns the interprocess_semaphore count // int get_count() const; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION @@ -99,7 +99,7 @@ class interprocess_semaphore #undef BOOST_INTERPROCESS_USE_POSIX ipcdetail::posix_semaphore m_sem; #endif //#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; } //namespace interprocess { diff --git a/boost/interprocess/sync/interprocess_sharable_mutex.hpp b/boost/interprocess/sync/interprocess_sharable_mutex.hpp new file mode 100644 index 0000000000..fbaf22a45f --- /dev/null +++ b/boost/interprocess/sync/interprocess_sharable_mutex.hpp @@ -0,0 +1,345 @@ +////////////////////////////////////////////////////////////////////////////// +// Code based on Howard Hinnant's shared_mutex class +// +// (C) Copyright Howard Hinnant 2007-2010. Distributed under the Boost +// Software License, Version 1.0. (see http://www.boost.org/LICENSE_1_0.txt) +// +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP +#define BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/sync/scoped_lock.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/interprocess_mutex.hpp> +#include <boost/interprocess/sync/interprocess_condition.hpp> +#include <climits> + + +//!\file +//!Describes interprocess_sharable_mutex class + +namespace boost { +namespace interprocess { + +//!Wraps a interprocess_sharable_mutex that can be placed in shared memory and can be +//!shared between processes. Allows timed lock tries +class interprocess_sharable_mutex +{ + //Non-copyable + interprocess_sharable_mutex(const interprocess_sharable_mutex &); + interprocess_sharable_mutex &operator=(const interprocess_sharable_mutex &); + + friend class interprocess_condition; + public: + + //!Constructs the sharable lock. + //!Throws interprocess_exception on error. + interprocess_sharable_mutex(); + + //!Destroys the sharable lock. + //!Does not throw. + ~interprocess_sharable_mutex(); + + //Exclusive locking + + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive or sharable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive or sharable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has exclusive or sharable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive ownership of the mutex, + //! waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has exclusive ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has exclusive + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock_sharable(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef scoped_lock<interprocess_mutex> scoped_lock_t; + + //Pack all the control data in a word to be able + //to use atomic instructions in the future + struct control_word_t + { + unsigned exclusive_in : 1; + unsigned num_shared : sizeof(unsigned)*CHAR_BIT-1; + } m_ctrl; + + interprocess_mutex m_mut; + interprocess_condition m_first_gate; + interprocess_condition m_second_gate; + + private: + //Rollback structures for exceptions or failure return values + struct exclusive_rollback + { + exclusive_rollback(control_word_t &ctrl + ,interprocess_condition &first_gate) + : mp_ctrl(&ctrl), m_first_gate(first_gate) + {} + + void release() + { mp_ctrl = 0; } + + ~exclusive_rollback() + { + if(mp_ctrl){ + mp_ctrl->exclusive_in = 0; + m_first_gate.notify_all(); + } + } + control_word_t *mp_ctrl; + interprocess_condition &m_first_gate; + }; + + template<int Dummy> + struct base_constants_t + { + static const unsigned max_readers + = ~(unsigned(1) << (sizeof(unsigned)*CHAR_BIT-1)); + }; + typedef base_constants_t<0> constants; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +template <int Dummy> +const unsigned interprocess_sharable_mutex::base_constants_t<Dummy>::max_readers; + +inline interprocess_sharable_mutex::interprocess_sharable_mutex() +{ + this->m_ctrl.exclusive_in = 0; + this->m_ctrl.num_shared = 0; +} + +inline interprocess_sharable_mutex::~interprocess_sharable_mutex() +{} + +inline void interprocess_sharable_mutex::lock() +{ + scoped_lock_t lck(m_mut); + + //The exclusive lock must block in the first gate + //if an exclusive lock has been acquired + while (this->m_ctrl.exclusive_in){ + this->m_first_gate.wait(lck); + } + + //Mark that exclusive lock has been acquired + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); + + //Now wait until all readers are gone + while (this->m_ctrl.num_shared){ + this->m_second_gate.wait(lck); + } + rollback.release(); +} + +inline bool interprocess_sharable_mutex::try_lock() +{ + scoped_lock_t lck(m_mut, try_to_lock); + + //If we can't lock or any has there is any exclusive + //or sharable mark return false; + if(!lck.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared){ + return false; + } + this->m_ctrl.exclusive_in = 1; + return true; +} + +inline bool interprocess_sharable_mutex::timed_lock + (const boost::posix_time::ptime &abs_time) +{ + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; + + //The exclusive lock must block in the first gate + //if an exclusive lock has been acquired + while (this->m_ctrl.exclusive_in){ + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.exclusive_in){ + return false; + } + break; + } + } + + //Mark that exclusive lock has been acquired + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); + + //Now wait until all readers are gone + while (this->m_ctrl.num_shared){ + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + if(!this->m_second_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.num_shared){ + return false; + } + break; + } + } + rollback.release(); + return true; +} + +inline void interprocess_sharable_mutex::unlock() +{ + scoped_lock_t lck(m_mut); + this->m_ctrl.exclusive_in = 0; + this->m_first_gate.notify_all(); +} + +//Sharable locking + +inline void interprocess_sharable_mutex::lock_sharable() +{ + scoped_lock_t lck(m_mut); + + //The sharable lock must block in the first gate + //if an exclusive lock has been acquired + //or there are too many sharable locks + while(this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + this->m_first_gate.wait(lck); + } + + //Increment sharable count + ++this->m_ctrl.num_shared; +} + +inline bool interprocess_sharable_mutex::try_lock_sharable() +{ + scoped_lock_t lck(m_mut, try_to_lock); + + //The sharable lock must fail + //if an exclusive lock has been acquired + //or there are too many sharable locks + if(!lck.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + return false; + } + + //Increment sharable count + ++this->m_ctrl.num_shared; + return true; +} + +inline bool interprocess_sharable_mutex::timed_lock_sharable + (const boost::posix_time::ptime &abs_time) +{ + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; + + //The sharable lock must block in the first gate + //if an exclusive lock has been acquired + //or there are too many sharable locks + while (this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + return false; + } + break; + } + } + + //Increment sharable count + ++this->m_ctrl.num_shared; + return true; +} + +inline void interprocess_sharable_mutex::unlock_sharable() +{ + scoped_lock_t lck(m_mut); + //Decrement sharable count + --this->m_ctrl.num_shared; + if (this->m_ctrl.num_shared == 0){ + this->m_second_gate.notify_one(); + } + //Check if there are blocked sharables because of + //there were too many sharables + else if(this->m_ctrl.num_shared == (constants::max_readers-1)){ + this->m_first_gate.notify_all(); + } +} + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP diff --git a/boost/interprocess/sync/interprocess_upgradable_mutex.hpp b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp index 8d5a452626..b90c71ef7f 100644 --- a/boost/interprocess/sync/interprocess_upgradable_mutex.hpp +++ b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp @@ -1,6 +1,8 @@ -////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// +// Code based on Howard Hinnant's upgrade_mutex class // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +13,7 @@ #ifndef BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP #define BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -195,7 +197,7 @@ class interprocess_upgradable_mutex //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock_upgradable(); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef scoped_lock<interprocess_mutex> scoped_lock_t; @@ -249,7 +251,7 @@ class interprocess_upgradable_mutex if(mp_ctrl){ //Recover upgradable lock mp_ctrl->upgradable_in = 1; - ++mp_ctrl->num_upr_shar; + ++mp_ctrl->num_upr_shar; //Execute the second half of exclusive locking mp_ctrl->exclusive_in = 0; } @@ -264,10 +266,10 @@ class interprocess_upgradable_mutex = ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2)); }; typedef base_constants_t<0> constants; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template <int Dummy> const unsigned interprocess_upgradable_mutex::base_constants_t<Dummy>::max_readers; @@ -284,12 +286,12 @@ inline interprocess_upgradable_mutex::~interprocess_upgradable_mutex() inline void interprocess_upgradable_mutex::lock() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //The exclusive lock must block in the first gate //if an exclusive or upgradable lock has been acquired while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ - this->m_first_gate.wait(lock); + this->m_first_gate.wait(lck); } //Mark that exclusive lock has been acquired @@ -300,18 +302,18 @@ inline void interprocess_upgradable_mutex::lock() //Now wait until all readers are gone while (this->m_ctrl.num_upr_shar){ - this->m_second_gate.wait(lock); + this->m_second_gate.wait(lck); } rollback.release(); } inline bool interprocess_upgradable_mutex::try_lock() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //If we can't lock or any has there is any exclusive, upgradable //or sharable mark return false; - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.exclusive_in || this->m_ctrl.num_upr_shar){ return false; @@ -323,18 +325,20 @@ inline bool interprocess_upgradable_mutex::try_lock() inline bool interprocess_upgradable_mutex::timed_lock (const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - scoped_lock_t lock(m_mut, abs_time); - if(!lock.owns()) return false; + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; //The exclusive lock must block in the first gate //if an exclusive or upgradable lock has been acquired while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ - if(!this->m_first_gate.timed_wait(lock, abs_time)) - return !(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in); + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ + return false; + } + break; + } } //Mark that exclusive lock has been acquired @@ -345,8 +349,11 @@ inline bool interprocess_upgradable_mutex::timed_lock //Now wait until all readers are gone while (this->m_ctrl.num_upr_shar){ - if(!this->m_second_gate.timed_wait(lock, abs_time)){ - return !(this->m_ctrl.num_upr_shar); + if(!this->m_second_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.num_upr_shar){ + return false; + } + break; } } rollback.release(); @@ -355,7 +362,7 @@ inline bool interprocess_upgradable_mutex::timed_lock inline void interprocess_upgradable_mutex::unlock() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); this->m_ctrl.exclusive_in = 0; this->m_first_gate.notify_all(); } @@ -364,14 +371,14 @@ inline void interprocess_upgradable_mutex::unlock() inline void interprocess_upgradable_mutex::lock_upgradable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //The upgradable lock must block in the first gate //if an exclusive or upgradable lock has been acquired //or there are too many sharable locks while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers){ - this->m_first_gate.wait(lock); + this->m_first_gate.wait(lck); } //Mark that upgradable lock has been acquired @@ -382,12 +389,12 @@ inline void interprocess_upgradable_mutex::lock_upgradable() inline bool interprocess_upgradable_mutex::try_lock_upgradable() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //The upgradable lock must fail //if an exclusive or upgradable lock has been acquired //or there are too many sharable locks - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers){ @@ -404,12 +411,10 @@ inline bool interprocess_upgradable_mutex::try_lock_upgradable() inline bool interprocess_upgradable_mutex::timed_lock_upgradable (const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->lock_upgradable(); - return true; - } - scoped_lock_t lock(m_mut, abs_time); - if(!lock.owns()) return false; + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; //The upgradable lock must block in the first gate //if an exclusive or upgradable lock has been acquired @@ -417,10 +422,13 @@ inline bool interprocess_upgradable_mutex::timed_lock_upgradable while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers){ - if(!this->m_first_gate.timed_wait(lock, abs_time)){ - return!(this->m_ctrl.exclusive_in - || this->m_ctrl.upgradable_in - || this->m_ctrl.num_upr_shar == constants::max_readers); + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if((this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar == constants::max_readers)){ + return false; + } + break; } } @@ -433,7 +441,7 @@ inline bool interprocess_upgradable_mutex::timed_lock_upgradable inline void interprocess_upgradable_mutex::unlock_upgradable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Mark that upgradable lock has been acquired //And add upgradable to the sharable count this->m_ctrl.upgradable_in = 0; @@ -445,14 +453,14 @@ inline void interprocess_upgradable_mutex::unlock_upgradable() inline void interprocess_upgradable_mutex::lock_sharable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //The sharable lock must block in the first gate //if an exclusive lock has been acquired //or there are too many sharable locks while(this->m_ctrl.exclusive_in || this->m_ctrl.num_upr_shar == constants::max_readers){ - this->m_first_gate.wait(lock); + this->m_first_gate.wait(lck); } //Increment sharable count @@ -461,12 +469,12 @@ inline void interprocess_upgradable_mutex::lock_sharable() inline bool interprocess_upgradable_mutex::try_lock_sharable() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //The sharable lock must fail //if an exclusive lock has been acquired //or there are too many sharable locks - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.exclusive_in || this->m_ctrl.num_upr_shar == constants::max_readers){ return false; @@ -480,21 +488,22 @@ inline bool interprocess_upgradable_mutex::try_lock_sharable() inline bool interprocess_upgradable_mutex::timed_lock_sharable (const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->lock_sharable(); - return true; - } - scoped_lock_t lock(m_mut, abs_time); - if(!lock.owns()) return false; + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; //The sharable lock must block in the first gate //if an exclusive lock has been acquired //or there are too many sharable locks while (this->m_ctrl.exclusive_in || this->m_ctrl.num_upr_shar == constants::max_readers){ - if(!this->m_first_gate.timed_wait(lock, abs_time)){ - return!(this->m_ctrl.exclusive_in - || this->m_ctrl.num_upr_shar == constants::max_readers); + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + return false; + } + break; } } @@ -505,7 +514,7 @@ inline bool interprocess_upgradable_mutex::timed_lock_sharable inline void interprocess_upgradable_mutex::unlock_sharable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Decrement sharable count --this->m_ctrl.num_upr_shar; if (this->m_ctrl.num_upr_shar == 0){ @@ -522,7 +531,7 @@ inline void interprocess_upgradable_mutex::unlock_sharable() inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Unmark it as exclusive this->m_ctrl.exclusive_in = 0; //Mark it as upgradable @@ -535,7 +544,7 @@ inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable() inline void interprocess_upgradable_mutex::unlock_and_lock_sharable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Unmark it as exclusive this->m_ctrl.exclusive_in = 0; //The sharable count should be 0 so increment it @@ -546,7 +555,7 @@ inline void interprocess_upgradable_mutex::unlock_and_lock_sharable() inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Unmark it as upgradable (we don't have to decrement count) this->m_ctrl.upgradable_in = 0; //Notify readers/upgradable that they can enter @@ -557,11 +566,11 @@ inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable() inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Simulate unlock_upgradable() without //notifying sharables. this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; //Execute the second half of exclusive locking this->m_ctrl.exclusive_in = 1; @@ -569,22 +578,22 @@ inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock() upgradable_to_exclusive_rollback rollback(m_ctrl); while (this->m_ctrl.num_upr_shar){ - this->m_second_gate.wait(lock); + this->m_second_gate.wait(lck); } rollback.release(); } inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //Check if there are no readers - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.num_upr_shar != 1){ return false; } //Now unlock upgradable and mark exclusive this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; this->m_ctrl.exclusive_in = 1; return true; } @@ -592,13 +601,15 @@ inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock() inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock (const boost::posix_time::ptime &abs_time) { - scoped_lock_t lock(m_mut, abs_time); - if(!lock.owns()) return false; + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; //Simulate unlock_upgradable() without //notifying sharables. this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; //Execute the second half of exclusive locking this->m_ctrl.exclusive_in = 1; @@ -606,8 +617,11 @@ inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock upgradable_to_exclusive_rollback rollback(m_ctrl); while (this->m_ctrl.num_upr_shar){ - if(!this->m_second_gate.timed_wait(lock, abs_time)){ - return !(this->m_ctrl.num_upr_shar); + if(!this->m_second_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.num_upr_shar){ + return false; + } + break; } } rollback.release(); @@ -616,11 +630,11 @@ inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //If we can't lock or any has there is any exclusive, upgradable //or sharable mark return false; - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar != 1){ @@ -633,11 +647,11 @@ inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock() inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //The upgradable lock must fail //if an exclusive or upgradable lock has been acquired - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ return false; @@ -648,7 +662,7 @@ inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradab return true; } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/sync/lock_options.hpp b/boost/interprocess/sync/lock_options.hpp index 74f3399a4c..7e3305ba44 100644 --- a/boost/interprocess/sync/lock_options.hpp +++ b/boost/interprocess/sync/lock_options.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_LOCK_OPTIONS_HPP #define BOOST_INTERPROCESS_LOCK_OPTIONS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -23,9 +23,13 @@ namespace boost { +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + namespace posix_time { class ptime; } +#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + namespace interprocess { //!Type to indicate to a mutex lock constructor that must not lock the mutex. diff --git a/boost/interprocess/sync/mutex_family.hpp b/boost/interprocess/sync/mutex_family.hpp index b153ffea3e..f19805f1b2 100644 --- a/boost/interprocess/sync/mutex_family.hpp +++ b/boost/interprocess/sync/mutex_family.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MUTEX_FAMILY_HPP #define BOOST_INTERPROCESS_MUTEX_FAMILY_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/sync/named_condition.hpp b/boost/interprocess/sync/named_condition.hpp index ca0205ad73..4f0d61e253 100644 --- a/boost/interprocess/sync/named_condition.hpp +++ b/boost/interprocess/sync/named_condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_NAMED_CONDITION_HPP #define BOOST_INTERPROCESS_NAMED_CONDITION_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -22,6 +22,7 @@ #include <boost/interprocess/detail/interprocess_tester.hpp> #include <boost/interprocess/permissions.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/detail/locks.hpp> #if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) #include <boost/interprocess/sync/windows/named_condition.hpp> #define BOOST_INTERPROCESS_USE_WINDOWS @@ -35,21 +36,21 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail{ class interprocess_tester; } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //! A global condition variable that can be created by name. //! This condition variable is designed to work with named_mutex and //! can't be placed in shared memory or memory mapped files. class named_condition { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable named_condition(); named_condition(const named_condition &); named_condition &operator=(const named_condition &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Creates a global condition with a name. //!If the condition can't be created throws interprocess_exception @@ -113,7 +114,7 @@ class named_condition //!Returns false on error. Never throws. static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: #if defined(BOOST_INTERPROCESS_USE_WINDOWS) typedef ipcdetail::windows_named_condition condition_type; @@ -125,10 +126,10 @@ class named_condition friend class ipcdetail::interprocess_tester; void dont_close_on_destruction() { ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline named_condition::~named_condition() {} @@ -153,26 +154,40 @@ inline void named_condition::notify_all() template <typename L> inline void named_condition::wait(L& lock) -{ m_cond.wait(lock); } +{ + ipcdetail::internal_mutex_lock<L> internal_lock(lock); + m_cond.wait(internal_lock); +} template <typename L, typename Pr> inline void named_condition::wait(L& lock, Pr pred) -{ m_cond.wait(lock, pred); } +{ + ipcdetail::internal_mutex_lock<L> internal_lock(lock); + m_cond.wait(internal_lock, pred); +} template <typename L> inline bool named_condition::timed_wait (L& lock, const boost::posix_time::ptime &abs_time) -{ return m_cond.timed_wait(lock, abs_time); } +{ + ipcdetail::internal_mutex_lock<L> internal_lock(lock); + return m_cond.timed_wait(internal_lock, abs_time); +} template <typename L, typename Pr> inline bool named_condition::timed_wait (L& lock, const boost::posix_time::ptime &abs_time, Pr pred) -{ return m_cond.timed_wait(lock, abs_time, pred); } +{ + ipcdetail::internal_mutex_lock<L> internal_lock(lock); + return m_cond.timed_wait(internal_lock, abs_time, pred); +} inline bool named_condition::remove(const char *name) -{ return condition_type::remove(name); } +{ + return condition_type::remove(name); +} -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess } //namespace boost diff --git a/boost/interprocess/sync/named_condition_any.hpp b/boost/interprocess/sync/named_condition_any.hpp new file mode 100644 index 0000000000..5d99d22ddd --- /dev/null +++ b/boost/interprocess/sync/named_condition_any.hpp @@ -0,0 +1,151 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP +#define BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/creation_tags.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <boost/interprocess/detail/interprocess_tester.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/detail/locks.hpp> +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/named_condition_any.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS +#else + #include <boost/interprocess/sync/shm/named_condition_any.hpp> +#endif + +//!\file +//!Describes a named condition class for inter-process synchronization + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +namespace ipcdetail{ class interprocess_tester; } +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//! A global condition variable that can be created by name. +//! This condition variable is designed to work with named_mutex and +//! can't be placed in shared memory or memory mapped files. +class named_condition_any +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + named_condition_any(); + named_condition_any(const named_condition_any &); + named_condition_any &operator=(const named_condition_any &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + named_condition_any(create_only_t, const char *name, const permissions &perm = permissions()) + : m_cond(create_only_t(), name, perm) + {} + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!named_condition_any(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!named_condition_any(open_only_t, ... ) + //!Does not throw + named_condition_any(open_or_create_t, const char *name, const permissions &perm = permissions()) + : m_cond(open_or_create_t(), name, perm) + {} + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_condition_any(open_only_t, const char *name) + : m_cond(open_only_t(), name) + {} + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_condition_any() + {} + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect.*/ + void notify_one() + { m_cond.notify_one(); } + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all() + { m_cond.notify_all(); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template <typename L> + void wait(L& lock) + { return m_cond.wait(lock); } + + //!The same as: + //!while (!pred()) wait(lock) + template <typename L, typename Pr> + void wait(L& lock, Pr pred) + { return m_cond.wait(lock, pred); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!and then reacquires the lock. + //!Returns: false if time abs_time is reached, otherwise true. + template <typename L> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { return m_cond.timed_wait(lock, abs_time); } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template <typename L, typename Pr> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { return m_cond.timed_wait(lock, abs_time, pred); } + + //!Erases a named condition from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name) + { return condition_any_type::remove(name); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + #if defined(BOOST_INTERPROCESS_USE_WINDOWS) + typedef ipcdetail::windows_named_condition_any condition_any_type; + #else + typedef ipcdetail::shm_named_condition_any condition_any_type; + #endif + condition_any_type m_cond; + + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction() + { ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} //namespace interprocess +} //namespace boost + +#include <boost/interprocess/detail/config_end.hpp> + +#endif // BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP diff --git a/boost/interprocess/sync/named_mutex.hpp b/boost/interprocess/sync/named_mutex.hpp index c34193c697..e91b1f4d8f 100644 --- a/boost/interprocess/sync/named_mutex.hpp +++ b/boost/interprocess/sync/named_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_NAMED_MUTEX_HPP #define BOOST_INTERPROCESS_NAMED_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -46,17 +46,17 @@ class named_condition; //!each process should have it's own named_mutex. class named_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable named_mutex(); named_mutex(const named_mutex &); named_mutex &operator=(const named_mutex &); friend class named_condition; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: - //!Creates a global interprocess_mutex with a name. + //!Creates a global mutex with a name. //!Throws interprocess_exception on error. named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); @@ -82,19 +82,19 @@ class named_mutex ~named_mutex(); //!Unlocks a previously locked - //!interprocess_mutex. + //!mutex. void unlock(); - //!Locks interprocess_mutex, sleeps when interprocess_mutex is already locked. + //!Locks the mutex, sleeps when the mutex is already locked. //!Throws interprocess_exception if a severe error is found void lock(); - //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex + //!Tries to lock the mutex, returns false when the mutex //!is already locked, returns true when success. //!Throws interprocess_exception if a severe error is found bool try_lock(); - //!Tries to lock the interprocess_mutex until time abs_time, + //!Tries to lock the the mutex until time abs_time, //!Returns false when timeout expires, returns true when locks. //!Throws interprocess_exception if a severe error is found bool timed_lock(const boost::posix_time::ptime &abs_time); @@ -103,31 +103,30 @@ class named_mutex //!Returns false on error. Never throws. static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class ipcdetail::interprocess_tester; void dont_close_on_destruction(); + public: #if defined(BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES) - typedef ipcdetail::posix_named_mutex impl_t; - impl_t m_mut; + typedef ipcdetail::posix_named_mutex internal_mutex_type; #undef BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) - typedef ipcdetail::windows_named_mutex impl_t; - impl_t m_mut; + typedef ipcdetail::windows_named_mutex internal_mutex_type; #undef BOOST_INTERPROCESS_USE_WINDOWS #else - typedef ipcdetail::shm_named_mutex impl_t; - impl_t m_mut; - public: - interprocess_mutex *mutex() const - { return m_mut.mutex(); } + typedef ipcdetail::shm_named_mutex internal_mutex_type; #endif + internal_mutex_type &internal_mutex() + { return m_mut; } + + internal_mutex_type m_mut; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline named_mutex::named_mutex(create_only_t, const char *name, const permissions &perm) : m_mut(create_only_t(), name, perm) @@ -160,9 +159,9 @@ inline bool named_mutex::timed_lock(const boost::posix_time::ptime &abs_time) { return m_mut.timed_lock(abs_time); } inline bool named_mutex::remove(const char *name) -{ return impl_t::remove(name); } +{ return internal_mutex_type::remove(name); } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/sync/named_recursive_mutex.hpp b/boost/interprocess/sync/named_recursive_mutex.hpp index 2d4b9b2416..f1f629dfcb 100644 --- a/boost/interprocess/sync/named_recursive_mutex.hpp +++ b/boost/interprocess/sync/named_recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP #define BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -33,21 +33,21 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail{ class interprocess_tester; } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!A recursive mutex with a global name, so it can be found from different //!processes. This mutex can't be placed in shared memory, and //!each process should have it's own named_recursive_mutex. class named_recursive_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable named_recursive_mutex(); named_recursive_mutex(const named_recursive_mutex &); named_recursive_mutex &operator=(const named_recursive_mutex &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Creates a global recursive_mutex with a name. @@ -97,7 +97,7 @@ class named_recursive_mutex //!from the system static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class ipcdetail::interprocess_tester; void dont_close_on_destruction(); @@ -110,10 +110,10 @@ class named_recursive_mutex #endif impl_t m_mut; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline named_recursive_mutex::~named_recursive_mutex() {} @@ -143,18 +143,12 @@ inline bool named_recursive_mutex::try_lock() { return m_mut.try_lock(); } inline bool named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - return m_mut.timed_lock(abs_time); -} +{ return m_mut.timed_lock(abs_time); } inline bool named_recursive_mutex::remove(const char *name) { return impl_t::remove(name); } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/sync/named_semaphore.hpp b/boost/interprocess/sync/named_semaphore.hpp index 39c9096fb6..c4a421ec2b 100644 --- a/boost/interprocess/sync/named_semaphore.hpp +++ b/boost/interprocess/sync/named_semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP #define BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -44,13 +44,13 @@ namespace interprocess { //!acknowledgment mechanisms. class named_semaphore { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable named_semaphore(); named_semaphore(const named_semaphore &); named_semaphore &operator=(const named_semaphore &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Creates a global semaphore with a name, and an initial count. @@ -104,7 +104,7 @@ class named_semaphore //!Returns false on error. Never throws. static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class ipcdetail::interprocess_tester; void dont_close_on_destruction(); @@ -118,10 +118,10 @@ class named_semaphore typedef ipcdetail::shm_named_semaphore impl_t; #endif impl_t m_sem; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline named_semaphore::named_semaphore (create_only_t, const char *name, unsigned int initialCount, const permissions &perm) @@ -153,18 +153,12 @@ inline bool named_semaphore::try_wait() { return m_sem.try_wait(); } inline bool named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->wait(); - return true; - } - return m_sem.timed_wait(abs_time); -} +{ return m_sem.timed_wait(abs_time); } inline bool named_semaphore::remove(const char *name) { return impl_t::remove(name); } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/sync/named_sharable_mutex.hpp b/boost/interprocess/sync/named_sharable_mutex.hpp new file mode 100644 index 0000000000..f4c0aaaee9 --- /dev/null +++ b/boost/interprocess/sync/named_sharable_mutex.hpp @@ -0,0 +1,230 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP +#define BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/creation_tags.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <boost/interprocess/shared_memory_object.hpp> +#include <boost/interprocess/detail/managed_open_or_create_impl.hpp> +#include <boost/interprocess/sync/interprocess_sharable_mutex.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/shm/named_creation_functor.hpp> +#include <boost/interprocess/permissions.hpp> + +//!\file +//!Describes a named sharable mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +namespace ipcdetail{ class interprocess_tester; } +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +class named_condition; + +//!A sharable mutex with a global name, so it can be found from different +//!processes. This mutex can't be placed in shared memory, and +//!each process should have it's own named sharable mutex. +class named_sharable_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + named_sharable_mutex(); + named_sharable_mutex(const named_sharable_mutex &); + named_sharable_mutex &operator=(const named_sharable_mutex &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Creates a global sharable mutex with a name. + //!If the sharable mutex can't be created throws interprocess_exception + named_sharable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); + + //!Opens or creates a global sharable mutex with a name. + //!If the sharable mutex is created, this call is equivalent to + //!named_sharable_mutex(create_only_t, ...) + //!If the sharable mutex is already created, this call is equivalent to + //!named_sharable_mutex(open_only_t, ... ). + named_sharable_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions()); + + //!Opens a global sharable mutex with a name if that sharable mutex + //!is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_sharable_mutex(open_only_t open_only, const char *name); + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_sharable_mutex(); + + //Exclusive locking + + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive or sharable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive or sharable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has exclusive, or sharable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive ownership of the mutex, + //! waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has exclusive ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has exclusive + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock_sharable(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + //!Erases a named sharable mutex from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction(); + + interprocess_sharable_mutex *mutex() const + { return static_cast<interprocess_sharable_mutex*>(m_shmem.get_user_address()); } + + typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t; + open_create_impl_t m_shmem; + typedef ipcdetail::named_creation_functor<interprocess_sharable_mutex> construct_func_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_sharable_mutex::~named_sharable_mutex() +{} + +inline named_sharable_mutex::named_sharable_mutex + (create_only_t, const char *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_sharable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline named_sharable_mutex::named_sharable_mutex + (open_or_create_t, const char *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_sharable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline named_sharable_mutex::named_sharable_mutex + (open_only_t, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +inline void named_sharable_mutex::dont_close_on_destruction() +{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline void named_sharable_mutex::lock() +{ this->mutex()->lock(); } + +inline void named_sharable_mutex::unlock() +{ this->mutex()->unlock(); } + +inline bool named_sharable_mutex::try_lock() +{ return this->mutex()->try_lock(); } + +inline bool named_sharable_mutex::timed_lock + (const boost::posix_time::ptime &abs_time) +{ return this->mutex()->timed_lock(abs_time); } + +inline void named_sharable_mutex::lock_sharable() +{ this->mutex()->lock_sharable(); } + +inline void named_sharable_mutex::unlock_sharable() +{ this->mutex()->unlock_sharable(); } + +inline bool named_sharable_mutex::try_lock_sharable() +{ return this->mutex()->try_lock_sharable(); } + +inline bool named_sharable_mutex::timed_lock_sharable + (const boost::posix_time::ptime &abs_time) +{ return this->mutex()->timed_lock_sharable(abs_time); } + +inline bool named_sharable_mutex::remove(const char *name) +{ return shared_memory_object::remove(name); } + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP diff --git a/boost/interprocess/sync/named_upgradable_mutex.hpp b/boost/interprocess/sync/named_upgradable_mutex.hpp index c45fd08270..e313e72ed4 100644 --- a/boost/interprocess/sync/named_upgradable_mutex.hpp +++ b/boost/interprocess/sync/named_upgradable_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_named_upgradable_mutex_HPP #define BOOST_INTERPROCESS_named_upgradable_mutex_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -32,9 +32,9 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail{ class interprocess_tester; } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED class named_condition; @@ -43,20 +43,20 @@ class named_condition; //!each process should have it's own named upgradable mutex. class named_upgradable_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable named_upgradable_mutex(); named_upgradable_mutex(const named_upgradable_mutex &); named_upgradable_mutex &operator=(const named_upgradable_mutex &); friend class named_condition; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Creates a global upgradable mutex with a name. //!If the upgradable mutex can't be created throws interprocess_exception named_upgradable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global upgradable mutex with a name, and an initial count. + //!Opens or creates a global upgradable mutex with a name. //!If the upgradable mutex is created, this call is equivalent to //!named_upgradable_mutex(create_only_t, ...) //!If the upgradable mutex is already created, this call is equivalent to @@ -215,13 +215,19 @@ class named_upgradable_mutex //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock(); + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The thread atomically releases sharable ownership and tries to acquire + //! upgradable ownership. This operation will fail if there are threads with sharable + //! or upgradable ownership, but it will maintain sharable ownership. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock_upgradable(); //!Erases a named upgradable mutex from the system. //!Returns false on error. Never throws. static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class ipcdetail::interprocess_tester; void dont_close_on_destruction(); @@ -229,12 +235,13 @@ class named_upgradable_mutex interprocess_upgradable_mutex *mutex() const { return static_cast<interprocess_upgradable_mutex*>(m_shmem.get_user_address()); } - ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem; + typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t; + open_create_impl_t m_shmem; typedef ipcdetail::named_creation_functor<interprocess_upgradable_mutex> construct_func_t; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline named_upgradable_mutex::~named_upgradable_mutex() {} @@ -244,8 +251,7 @@ inline named_upgradable_mutex::named_upgradable_mutex : m_shmem (create_only ,name ,sizeof(interprocess_upgradable_mutex) + - ipcdetail::managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(ipcdetail::DoCreate) @@ -257,8 +263,7 @@ inline named_upgradable_mutex::named_upgradable_mutex : m_shmem (open_or_create ,name ,sizeof(interprocess_upgradable_mutex) + - ipcdetail::managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(ipcdetail::DoOpenOrCreate) @@ -288,13 +293,7 @@ inline bool named_upgradable_mutex::try_lock() inline bool named_upgradable_mutex::timed_lock (const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - return this->mutex()->timed_lock(abs_time); -} +{ return this->mutex()->timed_lock(abs_time); } inline void named_upgradable_mutex::lock_upgradable() { this->mutex()->lock_upgradable(); } @@ -307,13 +306,7 @@ inline bool named_upgradable_mutex::try_lock_upgradable() inline bool named_upgradable_mutex::timed_lock_upgradable (const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock_upgradable(); - return true; - } - return this->mutex()->timed_lock_upgradable(abs_time); -} +{ return this->mutex()->timed_lock_upgradable(abs_time); } inline void named_upgradable_mutex::lock_sharable() { this->mutex()->lock_sharable(); } @@ -326,13 +319,7 @@ inline bool named_upgradable_mutex::try_lock_sharable() inline bool named_upgradable_mutex::timed_lock_sharable (const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock_sharable(); - return true; - } - return this->mutex()->timed_lock_sharable(abs_time); -} +{ return this->mutex()->timed_lock_sharable(abs_time); } inline void named_upgradable_mutex::unlock_and_lock_upgradable() { this->mutex()->unlock_and_lock_upgradable(); } @@ -362,7 +349,7 @@ inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() inline bool named_upgradable_mutex::remove(const char *name) { return shared_memory_object::remove(name); } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/sync/null_mutex.hpp b/boost/interprocess/sync/null_mutex.hpp index afe444ed3f..16db64b8d2 100644 --- a/boost/interprocess/sync/null_mutex.hpp +++ b/boost/interprocess/sync/null_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_NULL_MUTEX_HPP #define BOOST_INTERPROCESS_NULL_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -24,19 +24,23 @@ namespace boost { +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + namespace posix_time { class ptime; } +#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + namespace interprocess { //!Implements a mutex that simulates a mutex without doing any operation and //!simulates a successful operation. class null_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) null_mutex(const null_mutex&); null_mutex &operator= (const null_mutex&); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. diff --git a/boost/interprocess/sync/posix/condition.hpp b/boost/interprocess/sync/posix/condition.hpp index 48be099f60..e09fe4a109 100644 --- a/boost/interprocess/sync/posix/condition.hpp +++ b/boost/interprocess/sync/posix/condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_POSIX_CONDITION_HPP #define BOOST_INTERPROCESS_POSIX_CONDITION_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -19,7 +19,7 @@ #include <boost/interprocess/detail/workaround.hpp> #include <pthread.h> -#include <errno.h> +#include <errno.h> #include <boost/interprocess/sync/posix/pthread_helpers.hpp> #include <boost/interprocess/sync/posix/ptime_to_timespec.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> @@ -83,12 +83,13 @@ class posix_condition template <typename L> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) { + if (!lock) + throw lock_exception(); + //Posix does not support infinity absolute time so handle it here if(abs_time == boost::posix_time::pos_infin){ this->wait(lock); return true; } - if (!lock) - throw lock_exception(); return this->do_timed_wait(abs_time, *lock.mutex()); } @@ -98,17 +99,17 @@ class posix_condition template <typename L, typename Pr> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) { + if (!lock) + throw lock_exception(); + //Posix does not support infinity absolute time so handle it here if(abs_time == boost::posix_time::pos_infin){ this->wait(lock, pred); return true; } - if (!lock) - throw lock_exception(); while (!pred()){ if (!this->do_timed_wait(abs_time, *lock.mutex())) return pred(); } - return true; } @@ -145,21 +146,21 @@ inline posix_condition::~posix_condition() { int res = 0; res = pthread_cond_destroy(&m_condition); - BOOST_ASSERT(res == 0); + BOOST_ASSERT(res == 0); (void)res; } inline void posix_condition::notify_one() { int res = 0; res = pthread_cond_signal(&m_condition); - BOOST_ASSERT(res == 0); + BOOST_ASSERT(res == 0); (void)res; } inline void posix_condition::notify_all() { int res = 0; res = pthread_cond_broadcast(&m_condition); - BOOST_ASSERT(res == 0); + BOOST_ASSERT(res == 0); (void)res; } inline void posix_condition::do_wait(posix_mutex &mut) @@ -167,7 +168,7 @@ inline void posix_condition::do_wait(posix_mutex &mut) pthread_mutex_t* pmutex = &mut.m_mut; int res = 0; res = pthread_cond_wait(&m_condition, pmutex); - BOOST_ASSERT(res == 0); + BOOST_ASSERT(res == 0); (void)res; } inline bool posix_condition::do_timed_wait diff --git a/boost/interprocess/sync/posix/mutex.hpp b/boost/interprocess/sync/posix/mutex.hpp index 393807c97a..4cd4207061 100644 --- a/boost/interprocess/sync/posix/mutex.hpp +++ b/boost/interprocess/sync/posix/mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -27,7 +27,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP #define BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -35,7 +35,7 @@ #include <boost/interprocess/detail/workaround.hpp> #include <pthread.h> -#include <errno.h> +#include <errno.h> #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/sync/posix/ptime_to_timespec.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> @@ -44,6 +44,7 @@ #ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS # include <boost/interprocess/detail/os_thread_functions.hpp> +# include <boost/interprocess/sync/detail/common_algorithms.hpp> #endif #include <boost/assert.hpp> @@ -102,12 +103,12 @@ inline bool posix_mutex::try_lock() inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time) { + #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS + //Posix does not support infinity absolute time so handle it here if(abs_time == boost::posix_time::pos_infin){ this->lock(); return true; } - #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS - timespec ts = ptime_to_timespec(abs_time); int res = pthread_mutex_timedlock(&m_mut, &ts); if (res != 0 && res != ETIMEDOUT) @@ -116,22 +117,7 @@ inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time) #else //BOOST_INTERPROCESS_POSIX_TIMEOUTS - //Obtain current count and target time - boost::posix_time::ptime now = microsec_clock::universal_time(); - - do{ - if(this->try_lock()){ - break; - } - now = microsec_clock::universal_time(); - - if(now >= abs_time){ - return false; - } - // relinquish current time slice - thread_yield(); - }while (true); - return true; + return ipcdetail::try_based_timed_lock(*this, abs_time); #endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS } @@ -140,6 +126,7 @@ inline void posix_mutex::unlock() { int res = 0; res = pthread_mutex_unlock(&m_mut); + (void)res; BOOST_ASSERT(res == 0); } diff --git a/boost/interprocess/sync/posix/named_mutex.hpp b/boost/interprocess/sync/posix/named_mutex.hpp index 931c731eff..2b3be2f8be 100644 --- a/boost/interprocess/sync/posix/named_mutex.hpp +++ b/boost/interprocess/sync/posix/named_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP #define BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -32,13 +32,13 @@ class named_condition; class posix_named_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) posix_named_mutex(); posix_named_mutex(const posix_named_mutex &); posix_named_mutex &operator=(const posix_named_mutex &); friend class named_condition; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: posix_named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); @@ -55,16 +55,16 @@ class posix_named_mutex bool timed_lock(const boost::posix_time::ptime &abs_time); static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class interprocess_tester; void dont_close_on_destruction(); posix_named_semaphore m_sem; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline posix_named_mutex::posix_named_mutex(create_only_t, const char *name, const permissions &perm) : m_sem(create_only, name, 1, perm) @@ -94,18 +94,12 @@ inline bool posix_named_mutex::try_lock() { return m_sem.try_wait(); } inline bool posix_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - return m_sem.timed_wait(abs_time); -} +{ return m_sem.timed_wait(abs_time); } inline bool posix_named_mutex::remove(const char *name) { return posix_named_semaphore::remove(name); } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace ipcdetail { } //namespace interprocess { diff --git a/boost/interprocess/sync/posix/named_semaphore.hpp b/boost/interprocess/sync/posix/named_semaphore.hpp index f0327a4618..03510e3baa 100644 --- a/boost/interprocess/sync/posix/named_semaphore.hpp +++ b/boost/interprocess/sync/posix/named_semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP #define BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -23,9 +23,9 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail{ class interprocess_tester; } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED namespace ipcdetail { diff --git a/boost/interprocess/sync/posix/pthread_helpers.hpp b/boost/interprocess/sync/posix/pthread_helpers.hpp index bcbc44be33..ce859d7918 100644 --- a/boost/interprocess/sync/posix/pthread_helpers.hpp +++ b/boost/interprocess/sync/posix/pthread_helpers.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP #define BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -19,8 +19,8 @@ #include <boost/interprocess/detail/workaround.hpp> #include <pthread.h> -#include <errno.h> -#include <boost/interprocess/exceptions.hpp> +#include <errno.h> +#include <boost/interprocess/exceptions.hpp> namespace boost { namespace interprocess { @@ -86,7 +86,7 @@ namespace ipcdetail{ void release() {mp_mut = 0; } - private: + private: pthread_mutex_t *mp_mut; }; @@ -105,7 +105,7 @@ namespace ipcdetail{ void release() { mp_cond = 0; } - private: + private: pthread_cond_t *mp_cond; }; @@ -151,7 +151,7 @@ namespace ipcdetail{ void release() {mp_barrier = 0; } - private: + private: pthread_barrier_t *mp_barrier; }; diff --git a/boost/interprocess/sync/posix/ptime_to_timespec.hpp b/boost/interprocess/sync/posix/ptime_to_timespec.hpp index 7d787353bd..65993de958 100644 --- a/boost/interprocess/sync/posix/ptime_to_timespec.hpp +++ b/boost/interprocess/sync/posix/ptime_to_timespec.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP #define BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/posix_time_types_wrk.hpp> namespace boost { @@ -22,7 +26,9 @@ namespace ipcdetail { inline timespec ptime_to_timespec (const boost::posix_time::ptime &tm) { const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); - boost::posix_time::time_duration duration (tm - epoch); + //Avoid negative absolute times + boost::posix_time::time_duration duration = (tm <= epoch) ? boost::posix_time::time_duration(epoch - epoch) + : boost::posix_time::time_duration(tm - epoch); timespec ts; ts.tv_sec = duration.total_seconds(); ts.tv_nsec = duration.total_nanoseconds() % 1000000000; diff --git a/boost/interprocess/sync/posix/recursive_mutex.hpp b/boost/interprocess/sync/posix/recursive_mutex.hpp index 456c9a4874..ccb50da286 100644 --- a/boost/interprocess/sync/posix/recursive_mutex.hpp +++ b/boost/interprocess/sync/posix/recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -27,17 +27,22 @@ #ifndef BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP #define BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <pthread.h> -#include <errno.h> +#include <errno.h> #include <boost/interprocess/sync/posix/pthread_helpers.hpp> #include <boost/interprocess/sync/posix/ptime_to_timespec.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> #include <boost/interprocess/exceptions.hpp> #ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS # include <boost/interprocess/detail/os_thread_functions.hpp> +# include <boost/interprocess/sync/detail/common_algorithms.hpp> #endif #include <boost/assert.hpp> @@ -92,11 +97,12 @@ inline bool posix_recursive_mutex::try_lock() inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time) { + #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS + //Posix does not support infinity absolute time so handle it here if(abs_time == boost::posix_time::pos_infin){ this->lock(); return true; } - #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS timespec ts = ptime_to_timespec(abs_time); int res = pthread_mutex_timedlock(&m_mut, &ts); @@ -106,22 +112,7 @@ inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &ab #else //BOOST_INTERPROCESS_POSIX_TIMEOUTS - //Obtain current count and target time - boost::posix_time::ptime now = microsec_clock::universal_time(); - - do{ - if(this->try_lock()){ - break; - } - now = microsec_clock::universal_time(); - - if(now >= abs_time){ - return false; - } - // relinquish current time slice - thread_yield(); - }while (true); - return true; + return ipcdetail::try_based_timed_lock(*this, abs_time); #endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS } @@ -130,7 +121,7 @@ inline void posix_recursive_mutex::unlock() { int res = 0; res = pthread_mutex_unlock(&m_mut); - BOOST_ASSERT(res == 0); + BOOST_ASSERT(res == 0); (void)res; } } //namespace ipcdetail { diff --git a/boost/interprocess/sync/posix/semaphore.hpp b/boost/interprocess/sync/posix/semaphore.hpp index b7f62cc42d..ba6a6f0eba 100644 --- a/boost/interprocess/sync/posix/semaphore.hpp +++ b/boost/interprocess/sync/posix/semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP #define BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/sync/posix/semaphore_wrapper.hpp b/boost/interprocess/sync/posix/semaphore_wrapper.hpp index 22184cda9d..33f55fae54 100644 --- a/boost/interprocess/sync/posix/semaphore_wrapper.hpp +++ b/boost/interprocess/sync/posix/semaphore_wrapper.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,11 +11,15 @@ #ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP #define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/posix_time_types_wrk.hpp> #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #include <boost/interprocess/permissions.hpp> #include <fcntl.h> //O_CREAT, O_*... @@ -35,6 +39,8 @@ #include <boost/interprocess/sync/posix/ptime_to_timespec.hpp> #else #include <boost/interprocess/detail/os_thread_functions.hpp> +#include <boost/interprocess/sync/detail/locks.hpp> +#include <boost/interprocess/sync/detail/common_algorithms.hpp> #endif namespace boost { @@ -49,7 +55,7 @@ inline bool semaphore_open #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES add_leading_slash(origname, name); #else - create_tmp_and_clean_old_and_get_filename(origname, name); + create_shared_dir_cleaning_old_and_get_filepath(origname, name); #endif //Create new mapping @@ -103,7 +109,7 @@ inline bool semaphore_open inline void semaphore_close(sem_t *handle) { int ret = sem_close(handle); - if(ret != 0){ + if(ret != 0){ BOOST_ASSERT(0); } } @@ -115,7 +121,7 @@ inline bool semaphore_unlink(const char *semname) #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES add_leading_slash(semname, sem_str); #else - tmp_filename(semname, sem_str); + shared_filepath(semname, sem_str); #endif return 0 == sem_unlink(sem_str.c_str()); } @@ -131,14 +137,15 @@ inline void semaphore_init(sem_t *handle, unsigned int initialCount) //sem_init call is not defined, but -1 is returned on failure. //In the future, a successful call might be required to return 0. if(ret == -1){ - throw interprocess_exception(system_error_code()); + error_info err = system_error_code(); + throw interprocess_exception(err); } } inline void semaphore_destroy(sem_t *handle) { int ret = sem_destroy(handle); - if(ret != 0){ + if(ret != 0){ BOOST_ASSERT(0); } } @@ -147,7 +154,8 @@ inline void semaphore_post(sem_t *handle) { int ret = sem_post(handle); if(ret != 0){ - throw interprocess_exception(system_error_code()); + error_info err = system_error_code(); + throw interprocess_exception(err); } } @@ -155,7 +163,8 @@ inline void semaphore_wait(sem_t *handle) { int ret = sem_wait(handle); if(ret != 0){ - throw interprocess_exception(system_error_code()); + error_info err = system_error_code(); + throw interprocess_exception(err); } } @@ -167,17 +176,39 @@ inline bool semaphore_try_wait(sem_t *handle) if(system_error_code() == EAGAIN){ return false; } - throw interprocess_exception(system_error_code()); - return false; + error_info err = system_error_code(); + throw interprocess_exception(err); } +#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS + +struct semaphore_wrapper_try_wrapper +{ + explicit semaphore_wrapper_try_wrapper(sem_t *handle) + : m_handle(handle) + {} + + void wait() + { semaphore_wait(m_handle); } + + bool try_wait() + { return semaphore_try_wait(m_handle); } + + private: + sem_t *m_handle; +}; + +#endif + inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time) { + #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS + //Posix does not support infinity absolute time so handle it here if(abs_time == boost::posix_time::pos_infin){ semaphore_wait(handle); return true; } - #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS + timespec tspec = ptime_to_timespec(abs_time); for (;;){ int res = sem_timedwait(handle, &tspec); @@ -190,17 +221,16 @@ inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime & if(system_error_code() == ETIMEDOUT){ return false; } - throw interprocess_exception(system_error_code()); + error_info err = system_error_code(); + throw interprocess_exception(err); } return false; #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS - boost::posix_time::ptime now; - do{ - if(semaphore_try_wait(handle)) - return true; - thread_yield(); - }while((now = microsec_clock::universal_time()) < abs_time); - return false; + + semaphore_wrapper_try_wrapper swtw(handle); + ipcdetail::lock_to_wait<semaphore_wrapper_try_wrapper> lw(swtw); + return ipcdetail::try_based_timed_lock(lw, abs_time); + #endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS } diff --git a/boost/interprocess/sync/scoped_lock.hpp b/boost/interprocess/sync/scoped_lock.hpp index 61fe93e5b3..c095530274 100644 --- a/boost/interprocess/sync/scoped_lock.hpp +++ b/boost/interprocess/sync/scoped_lock.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -16,7 +16,7 @@ #ifndef BOOST_INTERPROCESS_SCOPED_LOCK_HPP #define BOOST_INTERPROCESS_SCOPED_LOCK_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -27,7 +27,7 @@ #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/detail/mpl.hpp> #include <boost/interprocess/detail/type_traits.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> //!\file @@ -50,12 +50,12 @@ namespace interprocess { template <class Mutex> class scoped_lock { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef scoped_lock<Mutex> this_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_lock) typedef bool this_type::*unspecified_bool_type; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: typedef Mutex mutex_type; @@ -157,7 +157,7 @@ class scoped_lock //! a)if try_unlock_upgradable_and_lock() returns true then mutex() obtains //! the value from upgr.release() and owns() is set to true. //! b)if try_unlock_upgradable_and_lock() returns false then upgr is - //! unaffected and this scoped_lock construction as the same effects as + //! unaffected and this scoped_lock construction as the same effects as //! a default construction. //! c)Else upgr.owns() is false. mutex() obtains the value from upgr.release() //! and owns() is set to false @@ -259,7 +259,7 @@ class scoped_lock //! mutex after the assignment (and scop will not), but the mutex's lock //! count will be decremented by one. scoped_lock &operator=(BOOST_RV_REF(scoped_lock) scop) - { + { if(this->owns()) this->unlock(); m_locked = scop.owns(); @@ -357,11 +357,11 @@ class scoped_lock std::swap(m_locked, other.m_locked); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: mutex_type *mp_mutex; bool m_locked; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; } // namespace interprocess diff --git a/boost/interprocess/sync/sharable_lock.hpp b/boost/interprocess/sync/sharable_lock.hpp index 9342e45a46..efbee6d10a 100644 --- a/boost/interprocess/sync/sharable_lock.hpp +++ b/boost/interprocess/sync/sharable_lock.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -16,7 +16,7 @@ #ifndef BOOST_INTERPROCESS_SHARABLE_LOCK_HPP #define BOOST_INTERPROCESS_SHARABLE_LOCK_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -27,7 +27,7 @@ #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/detail/mpl.hpp> #include <boost/interprocess/detail/type_traits.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> //!\file @@ -51,13 +51,13 @@ class sharable_lock { public: typedef SharableMutex mutex_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef sharable_lock<SharableMutex> this_type; explicit sharable_lock(scoped_lock<mutex_type>&); typedef bool this_type::*unspecified_bool_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(sharable_lock) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Effects: Default constructs a sharable_lock. @@ -189,7 +189,7 @@ class sharable_lock //! before the assignment. In this case, this will own the mutex after the assignment //! (and upgr will not), but the mutex's lock count will be decremented by one. sharable_lock &operator=(BOOST_RV_REF(sharable_lock<mutex_type>) upgr) - { + { if(this->owns()) this->unlock(); m_locked = upgr.owns(); @@ -203,7 +203,7 @@ class sharable_lock //!Notes: The sharable_lock changes from a state of not owning the //! mutex, to owning the mutex, blocking if necessary. void lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); mp_mutex->lock_sharable(); @@ -219,7 +219,7 @@ class sharable_lock //! mutex_type does not support try_lock_sharable(), this function will //! fail at compile time if instantiated, but otherwise have no effect. bool try_lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->try_lock_sharable(); @@ -236,7 +236,7 @@ class sharable_lock //! timed_lock_sharable(), this function will fail at compile time if //! instantiated, but otherwise have no effect. bool timed_lock(const boost::posix_time::ptime& abs_time) - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->timed_lock_sharable(abs_time); @@ -290,11 +290,11 @@ class sharable_lock std::swap(m_locked, other.m_locked); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: mutex_type *mp_mutex; bool m_locked; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; } // namespace interprocess diff --git a/boost/interprocess/sync/shm/named_condition.hpp b/boost/interprocess/sync/shm/named_condition.hpp index 9d7cd77e11..e2ff280b7b 100644 --- a/boost/interprocess/sync/shm/named_condition.hpp +++ b/boost/interprocess/sync/shm/named_condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP #define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -29,8 +29,11 @@ #include <boost/interprocess/sync/named_mutex.hpp> #include <boost/interprocess/permissions.hpp> #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) -#include <boost/interprocess/sync/interprocess_mutex.hpp> -#include <boost/interprocess/sync/scoped_lock.hpp> + #include <boost/interprocess/sync/interprocess_mutex.hpp> + #include <boost/interprocess/sync/scoped_lock.hpp> + #include <boost/interprocess/sync/detail/condition_any_algorithm.hpp> +#else + #include <boost/interprocess/sync/detail/locks.hpp> #endif @@ -41,21 +44,21 @@ namespace boost { namespace interprocess { namespace ipcdetail { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) class interprocess_tester; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //! A global condition variable that can be created by name. //! This condition variable is designed to work with named_mutex and //! can't be placed in shared memory or memory mapped files. class shm_named_condition { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable shm_named_condition(); shm_named_condition(const shm_named_condition &); shm_named_condition &operator=(const shm_named_condition &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Creates a global condition with a name. //!If the condition can't be created throws interprocess_exception @@ -119,113 +122,44 @@ class shm_named_condition //!Returns false on error. Never throws. static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: - struct condition_holder + #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + class internal_condition_members { - interprocess_condition cond_; - //If named_mutex is implemented using semaphores - //we need to store an additional mutex - #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - interprocess_mutex mutex_; - #endif - }; + public: + typedef interprocess_mutex mutex_type; + typedef interprocess_condition condvar_type; - interprocess_condition *condition() const - { return &static_cast<condition_holder*>(m_shmem.get_user_address())->cond_; } + condvar_type& get_condvar() { return m_cond; } + mutex_type& get_mutex() { return m_mtx; } - template <class Lock> - class lock_inverter - { - Lock &l_; - public: - lock_inverter(Lock &l) - : l_(l) - {} - void lock() { l_.unlock(); } - void unlock() { l_.lock(); } + private: + mutex_type m_mtx; + condvar_type m_cond; }; - //If named mutex uses POSIX semaphores, then the shm based condition variable - //must use it's internal lock to wait, as sem_t does not store a pthread_mutex_t - //instance needed by pthread_mutex_cond_t - #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - interprocess_mutex *mutex() const - { return &static_cast<condition_holder*>(m_shmem.get_user_address())->mutex_; } - - template <class Lock> - void do_wait(Lock& lock) - { - //shm_named_condition only works with named_mutex - BOOST_STATIC_ASSERT((is_convertible<typename Lock::mutex_type&, named_mutex&>::value == true)); - - //lock internal before unlocking external to avoid race with a notifier - scoped_lock<interprocess_mutex> internal_lock(*this->mutex()); - lock_inverter<Lock> inverted_lock(lock); - scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock); - - //unlock internal first to avoid deadlock with near simultaneous waits - scoped_lock<interprocess_mutex> internal_unlock; - internal_lock.swap(internal_unlock); - this->condition()->wait(internal_unlock); - } - - template <class Lock> - bool do_timed_wait(Lock& lock, const boost::posix_time::ptime &abs_time) - { - //shm_named_condition only works with named_mutex - BOOST_STATIC_ASSERT((is_convertible<typename Lock::mutex_type&, named_mutex&>::value == true)); - //lock internal before unlocking external to avoid race with a notifier - scoped_lock<interprocess_mutex> internal_lock(*this->mutex(), abs_time); - if(!internal_lock) return false; - lock_inverter<Lock> inverted_lock(lock); - scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock); - - //unlock internal first to avoid deadlock with near simultaneous waits - scoped_lock<interprocess_mutex> internal_unlock; - internal_lock.swap(internal_unlock); - return this->condition()->timed_wait(internal_unlock, abs_time); - } - #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - template<class Lock> - class lock_wrapper - { - typedef void (lock_wrapper::*unspecified_bool_type)(); - public: - - typedef interprocess_mutex mutex_type; - - lock_wrapper(Lock &l) - : l_(l) - {} - - mutex_type* mutex() const - { return l_.mutex()->mutex(); } - - void lock() { l_.lock(); } - - void unlock() { l_.unlock(); } - - operator unspecified_bool_type() const - { return l_ ? &lock_wrapper::lock : 0; } - - private: - Lock &l_; - }; + typedef ipcdetail::condition_any_wrapper<internal_condition_members> internal_condition; + #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + typedef interprocess_condition internal_condition; #endif //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + internal_condition &internal_cond() + { return *static_cast<internal_condition*>(m_shmem.get_user_address()); } + friend class boost::interprocess::ipcdetail::interprocess_tester; void dont_close_on_destruction(); - managed_open_or_create_impl<shared_memory_object> m_shmem; + typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t; + open_create_impl_t m_shmem; template <class T, class Arg> friend class boost::interprocess::ipcdetail::named_creation_functor; - typedef boost::interprocess::ipcdetail::named_creation_functor<condition_holder> construct_func_t; - /// @endcond + typedef boost::interprocess::ipcdetail::named_creation_functor<internal_condition> construct_func_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline shm_named_condition::~shm_named_condition() {} @@ -233,9 +167,8 @@ inline shm_named_condition::~shm_named_condition() inline shm_named_condition::shm_named_condition(create_only_t, const char *name, const permissions &perm) : m_shmem (create_only ,name - ,sizeof(condition_holder) + - managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(DoCreate) @@ -245,9 +178,8 @@ inline shm_named_condition::shm_named_condition(create_only_t, const char *name, inline shm_named_condition::shm_named_condition(open_or_create_t, const char *name, const permissions &perm) : m_shmem (open_or_create ,name - ,sizeof(condition_holder) + - managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(DoOpenOrCreate) @@ -265,113 +197,34 @@ inline shm_named_condition::shm_named_condition(open_only_t, const char *name) inline void shm_named_condition::dont_close_on_destruction() { interprocess_tester::dont_close_on_destruction(m_shmem); } -#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - inline void shm_named_condition::notify_one() -{ - scoped_lock<interprocess_mutex> internal_lock(*this->mutex()); - this->condition()->notify_one(); -} +{ this->internal_cond().notify_one(); } inline void shm_named_condition::notify_all() -{ - scoped_lock<interprocess_mutex> internal_lock(*this->mutex()); - this->condition()->notify_all(); -} +{ this->internal_cond().notify_all(); } template <typename L> inline void shm_named_condition::wait(L& lock) -{ - if (!lock) - throw lock_exception(); - this->do_wait(lock); -} +{ this->internal_cond().wait(lock); } template <typename L, typename Pr> inline void shm_named_condition::wait(L& lock, Pr pred) -{ - if (!lock) - throw lock_exception(); - while (!pred()) - this->do_wait(lock); -} +{ this->internal_cond().wait(lock, pred); } template <typename L> inline bool shm_named_condition::timed_wait (L& lock, const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock); - return true; - } - if (!lock) - throw lock_exception(); - return this->do_timed_wait(lock, abs_time); -} +{ return this->internal_cond().timed_wait(lock, abs_time); } template <typename L, typename Pr> inline bool shm_named_condition::timed_wait (L& lock, const boost::posix_time::ptime &abs_time, Pr pred) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock, pred); - return true; - } - if (!lock) - throw lock_exception(); - - while (!pred()){ - if(!this->do_timed_wait(lock, abs_time)){ - return pred(); - } - } - return true; -} - -#else - -inline void shm_named_condition::notify_one() -{ this->condition()->notify_one(); } - -inline void shm_named_condition::notify_all() -{ this->condition()->notify_all(); } - -template <typename L> -inline void shm_named_condition::wait(L& lock) -{ - lock_wrapper<L> newlock(lock); - this->condition()->wait(newlock); -} - -template <typename L, typename Pr> -inline void shm_named_condition::wait(L& lock, Pr pred) -{ - lock_wrapper<L> newlock(lock); - this->condition()->wait(newlock, pred); -} - -template <typename L> -inline bool shm_named_condition::timed_wait - (L& lock, const boost::posix_time::ptime &abs_time) -{ - lock_wrapper<L> newlock(lock); - return this->condition()->timed_wait(newlock, abs_time); -} - -template <typename L, typename Pr> -inline bool shm_named_condition::timed_wait - (L& lock, const boost::posix_time::ptime &abs_time, Pr pred) -{ - lock_wrapper<L> newlock(lock); - return this->condition()->timed_wait(newlock, abs_time, pred); -} - -#endif +{ return this->internal_cond().timed_wait(lock, abs_time, pred); } inline bool shm_named_condition::remove(const char *name) { return shared_memory_object::remove(name); } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace ipcdetail } //namespace interprocess diff --git a/boost/interprocess/sync/shm/named_condition_any.hpp b/boost/interprocess/sync/shm/named_condition_any.hpp new file mode 100644 index 0000000000..46bca92e45 --- /dev/null +++ b/boost/interprocess/sync/shm/named_condition_any.hpp @@ -0,0 +1,191 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP +#define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/static_assert.hpp> +#include <boost/interprocess/detail/type_traits.hpp> +#include <boost/interprocess/creation_tags.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <boost/interprocess/shared_memory_object.hpp> +#include <boost/interprocess/sync/interprocess_condition.hpp> +#include <boost/interprocess/detail/managed_open_or_create_impl.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/shm/named_creation_functor.hpp> +#include <boost/interprocess/sync/named_mutex.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/sync/interprocess_mutex.hpp> +#include <boost/interprocess/sync/scoped_lock.hpp> +#include <boost/interprocess/sync/detail/condition_any_algorithm.hpp> + +//!\file +//!Describes process-shared variables interprocess_condition class + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +class interprocess_tester; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//! A global condition variable that can be created by name. +//! This condition variable is designed to work with named_mutex and +//! can't be placed in shared memory or memory mapped files. +class shm_named_condition_any +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + shm_named_condition_any(); + shm_named_condition_any(const shm_named_condition_any &); + shm_named_condition_any &operator=(const shm_named_condition_any &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + shm_named_condition_any(create_only_t create_only, const char *name, const permissions &perm = permissions()) + : m_shmem (create_only + ,name + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate) + ,perm) + {} + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!shm_named_condition_any(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!shm_named_condition_any(open_only_t, ... ) + //!Does not throw + shm_named_condition_any(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions()) + : m_shmem (open_or_create + ,name + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate) + ,perm) + {} + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + shm_named_condition_any(open_only_t open_only, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen)) + {} + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~shm_named_condition_any() + {} + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect.*/ + void notify_one() + { m_cond.notify_one(); } + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all() + { m_cond.notify_all(); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template <typename L> + void wait(L& lock) + { m_cond.wait(lock); } + + //!The same as: + //!while (!pred()) wait(lock) + template <typename L, typename Pr> + void wait(L& lock, Pr pred) + { m_cond.wait(lock, pred); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!and then reacquires the lock. + //!Returns: false if time abs_time is reached, otherwise true. + template <typename L> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { return m_cond.timed_wait(lock, abs_time); } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template <typename L, typename Pr> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { return m_cond.timed_wait(lock, abs_time, pred); } + + //!Erases a named condition from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name) + { return shared_memory_object::remove(name); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + class internal_condition_members + { + public: + typedef interprocess_mutex mutex_type; + typedef interprocess_condition condvar_type; + + condvar_type& get_condvar() { return m_cond; } + mutex_type& get_mutex() { return m_mtx; } + + private: + mutex_type m_mtx; + condvar_type m_cond; + }; + + typedef ipcdetail::condition_any_wrapper<internal_condition_members> internal_condition; + + internal_condition m_cond; + + friend class boost::interprocess::ipcdetail::interprocess_tester; + void dont_close_on_destruction() + { interprocess_tester::dont_close_on_destruction(m_shmem); } + + typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t; + open_create_impl_t m_shmem; + + template <class T, class Arg> friend class boost::interprocess::ipcdetail::named_creation_functor; + typedef boost::interprocess::ipcdetail::named_creation_functor<internal_condition> construct_func_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include <boost/interprocess/detail/config_end.hpp> + +#endif // BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP diff --git a/boost/interprocess/sync/shm/named_creation_functor.hpp b/boost/interprocess/sync/shm/named_creation_functor.hpp index 9d752c837a..234e072aac 100644 --- a/boost/interprocess/sync/shm/named_creation_functor.hpp +++ b/boost/interprocess/sync/shm/named_creation_functor.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP #define BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/detail/type_traits.hpp> #include <boost/interprocess/detail/mpl.hpp> @@ -38,7 +42,7 @@ class named_creation_functor { new(address)T(m_arg); } bool operator()(void *address, std::size_t, bool created) const - { + { switch(m_creation_type){ case DoOpen: return true; @@ -56,6 +60,10 @@ class named_creation_functor break; } } + + std::size_t get_min_size() const + { return sizeof(T); } + private: create_enum_t m_creation_type; Arg m_arg; diff --git a/boost/interprocess/sync/shm/named_mutex.hpp b/boost/interprocess/sync/shm/named_mutex.hpp index f32fa70044..fc66f3a704 100644 --- a/boost/interprocess/sync/shm/named_mutex.hpp +++ b/boost/interprocess/sync/shm/named_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP #define BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -42,14 +42,14 @@ class named_condition; //!each process should have it's own named mutex. class shm_named_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable shm_named_mutex(); shm_named_mutex(const shm_named_mutex &); shm_named_mutex &operator=(const shm_named_mutex &); friend class named_condition; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Creates a global interprocess_mutex with a name. @@ -99,20 +99,21 @@ class shm_named_mutex //!Returns false on error. Never throws. static bool remove(const char *name); - /// @cond - interprocess_mutex *mutex() const - { return static_cast<interprocess_mutex*>(m_shmem.get_user_address()); } + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef interprocess_mutex internal_mutex_type; + interprocess_mutex &internal_mutex() + { return *static_cast<interprocess_mutex*>(m_shmem.get_user_address()); } private: friend class ipcdetail::interprocess_tester; void dont_close_on_destruction(); - - ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem; + typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t; + open_create_impl_t m_shmem; typedef ipcdetail::named_creation_functor<interprocess_mutex> construct_func_t; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline void shm_named_mutex::dont_close_on_destruction() { ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } @@ -124,8 +125,7 @@ inline shm_named_mutex::shm_named_mutex(create_only_t, const char *name, const p : m_shmem (create_only ,name ,sizeof(interprocess_mutex) + - ipcdetail::managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(ipcdetail::DoCreate) @@ -136,8 +136,7 @@ inline shm_named_mutex::shm_named_mutex(open_or_create_t, const char *name, cons : m_shmem (open_or_create ,name ,sizeof(interprocess_mutex) + - ipcdetail::managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(ipcdetail::DoOpenOrCreate) @@ -153,27 +152,21 @@ inline shm_named_mutex::shm_named_mutex(open_only_t, const char *name) {} inline void shm_named_mutex::lock() -{ this->mutex()->lock(); } +{ this->internal_mutex().lock(); } inline void shm_named_mutex::unlock() -{ this->mutex()->unlock(); } +{ this->internal_mutex().unlock(); } inline bool shm_named_mutex::try_lock() -{ return this->mutex()->try_lock(); } +{ return this->internal_mutex().try_lock(); } inline bool shm_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - return this->mutex()->timed_lock(abs_time); -} +{ return this->internal_mutex().timed_lock(abs_time); } inline bool shm_named_mutex::remove(const char *name) { return shared_memory_object::remove(name); } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace ipcdetail { } //namespace interprocess { diff --git a/boost/interprocess/sync/shm/named_recursive_mutex.hpp b/boost/interprocess/sync/shm/named_recursive_mutex.hpp index 7235571254..988ef66315 100644 --- a/boost/interprocess/sync/shm/named_recursive_mutex.hpp +++ b/boost/interprocess/sync/shm/named_recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP #define BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -33,18 +33,18 @@ namespace boost { namespace interprocess { namespace ipcdetail { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) class interprocess_tester; -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED class shm_named_recursive_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable shm_named_recursive_mutex(); shm_named_recursive_mutex(const shm_named_recursive_mutex &); shm_named_recursive_mutex &operator=(const shm_named_recursive_mutex &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Creates a global recursive_mutex with a name. @@ -94,17 +94,17 @@ class shm_named_recursive_mutex //!from the system static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class interprocess_tester; void dont_close_on_destruction(); interprocess_recursive_mutex *mutex() const { return static_cast<interprocess_recursive_mutex*>(m_shmem.get_user_address()); } - - managed_open_or_create_impl<shared_memory_object> m_shmem; + typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t; + open_create_impl_t m_shmem; typedef named_creation_functor<interprocess_recursive_mutex> construct_func_t; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; inline shm_named_recursive_mutex::~shm_named_recursive_mutex() @@ -117,8 +117,7 @@ inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const : m_shmem (create_only ,name ,sizeof(interprocess_recursive_mutex) + - managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(DoCreate) @@ -129,8 +128,7 @@ inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, co : m_shmem (open_or_create ,name ,sizeof(interprocess_recursive_mutex) + - managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(DoOpenOrCreate) @@ -155,13 +153,7 @@ inline bool shm_named_recursive_mutex::try_lock() { return this->mutex()->try_lock(); } inline bool shm_named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - return this->mutex()->timed_lock(abs_time); -} +{ return this->mutex()->timed_lock(abs_time); } inline bool shm_named_recursive_mutex::remove(const char *name) { return shared_memory_object::remove(name); } diff --git a/boost/interprocess/sync/shm/named_semaphore.hpp b/boost/interprocess/sync/shm/named_semaphore.hpp index c6d3830db5..d952d12e14 100644 --- a/boost/interprocess/sync/shm/named_semaphore.hpp +++ b/boost/interprocess/sync/shm/named_semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP #define BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -33,13 +33,13 @@ namespace ipcdetail { class shm_named_semaphore { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable shm_named_semaphore(); shm_named_semaphore(const shm_named_semaphore &); shm_named_semaphore &operator=(const shm_named_semaphore &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: shm_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); @@ -57,7 +57,7 @@ class shm_named_semaphore static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class interprocess_tester; void dont_close_on_destruction(); @@ -65,9 +65,10 @@ class shm_named_semaphore interprocess_semaphore *semaphore() const { return static_cast<interprocess_semaphore*>(m_shmem.get_user_address()); } - managed_open_or_create_impl<shared_memory_object> m_shmem; + typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t; + open_create_impl_t m_shmem; typedef named_creation_functor<interprocess_semaphore, int> construct_func_t; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; inline shm_named_semaphore::~shm_named_semaphore() @@ -81,8 +82,7 @@ inline shm_named_semaphore::shm_named_semaphore : m_shmem (create_only ,name ,sizeof(interprocess_semaphore) + - managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(DoCreate, initialCount) @@ -94,8 +94,7 @@ inline shm_named_semaphore::shm_named_semaphore : m_shmem (open_or_create ,name ,sizeof(interprocess_semaphore) + - managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(DoOpenOrCreate, initialCount) @@ -121,13 +120,7 @@ inline bool shm_named_semaphore::try_wait() { return semaphore()->try_wait(); } inline bool shm_named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->wait(); - return true; - } - return semaphore()->timed_wait(abs_time); -} +{ return semaphore()->timed_wait(abs_time); } inline bool shm_named_semaphore::remove(const char *name) { return shared_memory_object::remove(name); } diff --git a/boost/interprocess/sync/shm/named_upgradable_mutex.hpp b/boost/interprocess/sync/shm/named_upgradable_mutex.hpp index 0975a6ed2b..4c397927fb 100644 --- a/boost/interprocess/sync/shm/named_upgradable_mutex.hpp +++ b/boost/interprocess/sync/shm/named_upgradable_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP #define BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -32,9 +32,9 @@ namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail{ class interprocess_tester; } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED class named_condition; @@ -43,13 +43,13 @@ class named_condition; //!each process should have it's own named upgradable mutex. class named_upgradable_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable named_upgradable_mutex(); named_upgradable_mutex(const named_upgradable_mutex &); named_upgradable_mutex &operator=(const named_upgradable_mutex &); friend class named_condition; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Creates a global upgradable mutex with a name. @@ -221,7 +221,7 @@ class named_upgradable_mutex //!Returns false on error. Never throws. static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class ipcdetail::interprocess_tester; void dont_close_on_destruction(); @@ -229,12 +229,13 @@ class named_upgradable_mutex interprocess_upgradable_mutex *mutex() const { return static_cast<interprocess_upgradable_mutex*>(m_shmem.get_user_address()); } - ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem; + typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t; + open_create_impl_t m_shmem; typedef ipcdetail::named_creation_functor<interprocess_upgradable_mutex> construct_func_t; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline named_upgradable_mutex::~named_upgradable_mutex() {} @@ -244,8 +245,7 @@ inline named_upgradable_mutex::named_upgradable_mutex : m_shmem (create_only ,name ,sizeof(interprocess_upgradable_mutex) + - ipcdetail::managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(ipcdetail::DoCreate) @@ -257,8 +257,7 @@ inline named_upgradable_mutex::named_upgradable_mutex : m_shmem (open_or_create ,name ,sizeof(interprocess_upgradable_mutex) + - ipcdetail::managed_open_or_create_impl<shared_memory_object>:: - ManagedOpenOrCreateUserOffset + open_create_impl_t::ManagedOpenOrCreateUserOffset ,read_write ,0 ,construct_func_t(ipcdetail::DoOpenOrCreate) @@ -288,13 +287,7 @@ inline bool named_upgradable_mutex::try_lock() inline bool named_upgradable_mutex::timed_lock (const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - return this->mutex()->timed_lock(abs_time); -} +{ return this->mutex()->timed_lock(abs_time); } inline void named_upgradable_mutex::lock_upgradable() { this->mutex()->lock_upgradable(); } @@ -307,13 +300,7 @@ inline bool named_upgradable_mutex::try_lock_upgradable() inline bool named_upgradable_mutex::timed_lock_upgradable (const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock_upgradable(); - return true; - } - return this->mutex()->timed_lock_upgradable(abs_time); -} +{ return this->mutex()->timed_lock_upgradable(abs_time); } inline void named_upgradable_mutex::lock_sharable() { this->mutex()->lock_sharable(); } @@ -326,13 +313,7 @@ inline bool named_upgradable_mutex::try_lock_sharable() inline bool named_upgradable_mutex::timed_lock_sharable (const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock_sharable(); - return true; - } - return this->mutex()->timed_lock_sharable(abs_time); -} +{ return this->mutex()->timed_lock_sharable(abs_time); } inline void named_upgradable_mutex::unlock_and_lock_upgradable() { this->mutex()->unlock_and_lock_upgradable(); } @@ -362,7 +343,7 @@ inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() inline bool named_upgradable_mutex::remove(const char *name) { return shared_memory_object::remove(name); } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/sync/spin/condition.hpp b/boost/interprocess/sync/spin/condition.hpp index 55dd79b406..e587c32c9b 100644 --- a/boost/interprocess/sync/spin/condition.hpp +++ b/boost/interprocess/sync/spin/condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP #define BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/sync/spin/mutex.hpp> @@ -19,7 +23,8 @@ #include <boost/interprocess/sync/scoped_lock.hpp> #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/detail/os_thread_functions.hpp> -#include <boost/move/move.hpp> +#include <boost/interprocess/sync/spin/wait.hpp> +#include <boost/move/utility_core.hpp> #include <boost/cstdint.hpp> namespace boost { @@ -40,24 +45,26 @@ class spin_condition template <typename L> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) { + if (!lock) + throw lock_exception(); + //Handle infinity absolute time here to avoid complications in do_timed_wait if(abs_time == boost::posix_time::pos_infin){ this->wait(lock); return true; } - if (!lock) - throw lock_exception(); return this->do_timed_wait(abs_time, *lock.mutex()); } template <typename L, typename Pr> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) { + if (!lock) + throw lock_exception(); + //Handle infinity absolute time here to avoid complications in do_timed_wait if(abs_time == boost::posix_time::pos_infin){ this->wait(lock, pred); return true; } - if (!lock) - throw lock_exception(); while (!pred()){ if (!this->do_timed_wait(abs_time, *lock.mutex())) return pred(); @@ -110,8 +117,10 @@ inline spin_condition::spin_condition() } inline spin_condition::~spin_condition() -{ - //Trivial destructor +{ + //Notify all waiting threads + //to allow POSIX semantics on condition destruction + this->notify_all(); } inline void spin_condition::notify_one() @@ -140,15 +149,10 @@ inline void spin_condition::notify(boost::uint32_t command) } //Notify that all threads should execute wait logic + spin_wait swait; while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), command, SLEEP)){ - thread_yield(); + swait.yield(); } -/* - //Wait until the threads are woken - while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), 0)){ - thread_yield(); - } -*/ //The enter mutex will rest locked until the last waiting thread unlocks it } @@ -171,7 +175,7 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, InterprocessMutex &mut) { boost::posix_time::ptime now = microsec_clock::universal_time(); - + if(tout_enabled){ if(now >= abs_time) return false; } @@ -205,14 +209,15 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, //By default, we suppose that no timeout has happened bool timed_out = false, unlock_enter_mut= false; - + //Loop until a notification indicates that the thread should //exit or timeout occurs while(1){ //The thread sleeps/spins until a spin_condition commands a notification //Notification occurred, we will lock the checking mutex so that + spin_wait swait; while(atomic_read32(&m_command) == SLEEP){ - thread_yield(); + swait.yield(); //Check for timeout if(tout_enabled){ @@ -253,7 +258,7 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, continue; } else if(result == NOTIFY_ONE){ - //If it was a NOTIFY_ONE command, only this thread should + //If it was a NOTIFY_ONE command, only this thread should //exit. This thread has atomically marked command as sleep before //so no other thread will exit. //Decrement wait count. diff --git a/boost/interprocess/sync/spin/interprocess_barrier.hpp b/boost/interprocess/sync/spin/interprocess_barrier.hpp index f8ee09948d..5f88dd4faa 100644 --- a/boost/interprocess/sync/spin/interprocess_barrier.hpp +++ b/boost/interprocess/sync/spin/interprocess_barrier.hpp @@ -12,6 +12,10 @@ #include <boost/interprocess/detail/posix_time_types_wrk.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> +#if defined(_MSC_VER) +# pragma once +#endif + namespace boost { namespace interprocess { diff --git a/boost/interprocess/sync/spin/mutex.hpp b/boost/interprocess/sync/spin/mutex.hpp index 926f7237c0..154dc6d916 100644 --- a/boost/interprocess/sync/spin/mutex.hpp +++ b/boost/interprocess/sync/spin/mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP #define BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -22,6 +22,7 @@ #include <boost/interprocess/detail/atomic.hpp> #include <boost/cstdint.hpp> #include <boost/interprocess/detail/os_thread_functions.hpp> +#include <boost/interprocess/sync/detail/common_algorithms.hpp> namespace boost { namespace interprocess { @@ -59,48 +60,16 @@ inline spin_mutex::~spin_mutex() } inline void spin_mutex::lock(void) -{ - do{ - boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0); - - if (m_s == 1 && prev_s == 0){ - break; - } - // relinquish current timeslice - ipcdetail::thread_yield(); - }while (true); -} +{ return ipcdetail::try_based_lock(*this); } inline bool spin_mutex::try_lock(void) { - boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0); + boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0); return m_s == 1 && prev_s == 0; } inline bool spin_mutex::timed_lock(const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - //Obtain current count and target time - boost::posix_time::ptime now = microsec_clock::universal_time(); - - do{ - if(this->try_lock()){ - break; - } - now = microsec_clock::universal_time(); - - if(now >= abs_time){ - return false; - } - // relinquish current time slice - ipcdetail::thread_yield(); - }while (true); - - return true; -} +{ return ipcdetail::try_based_timed_lock(*this, abs_time); } inline void spin_mutex::unlock(void) { ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 0, 1); } diff --git a/boost/interprocess/sync/spin/recursive_mutex.hpp b/boost/interprocess/sync/spin/recursive_mutex.hpp index a763f9c72d..ce6b0d18ac 100644 --- a/boost/interprocess/sync/spin/recursive_mutex.hpp +++ b/boost/interprocess/sync/spin/recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -27,7 +27,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP #define BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -118,10 +118,6 @@ inline bool spin_recursive_mutex::try_lock() inline bool spin_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time) { typedef ipcdetail::OS_systemwide_thread_id_t handle_t; - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id()); handle_t old_id; ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id); @@ -133,6 +129,7 @@ inline bool spin_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs ++m_nLockCount; return true; } + //m_mutex supports abs_time so no need to check it if(m_mutex.timed_lock(abs_time)){ ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner); m_nLockCount = 1; diff --git a/boost/interprocess/sync/spin/semaphore.hpp b/boost/interprocess/sync/spin/semaphore.hpp index 1b8cac35aa..94922afe43 100644 --- a/boost/interprocess/sync/spin/semaphore.hpp +++ b/boost/interprocess/sync/spin/semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP #define BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -20,6 +20,8 @@ #include <boost/interprocess/detail/atomic.hpp> #include <boost/interprocess/detail/os_thread_functions.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/detail/common_algorithms.hpp> +#include <boost/interprocess/sync/detail/locks.hpp> #include <boost/cstdint.hpp> namespace boost { @@ -59,11 +61,8 @@ inline void spin_semaphore::post() inline void spin_semaphore::wait() { - while(!ipcdetail::atomic_add_unless32(&m_count, boost::uint32_t(-1), boost::uint32_t(0))){ - while(ipcdetail::atomic_read32(&m_count) == 0){ - ipcdetail::thread_yield(); - } - } + ipcdetail::lock_to_wait<spin_semaphore> lw(*this); + return ipcdetail::try_based_lock(lw); } inline bool spin_semaphore::try_wait() @@ -73,29 +72,10 @@ inline bool spin_semaphore::try_wait() inline bool spin_semaphore::timed_wait(const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->wait(); - return true; - } - //Obtain current count and target time - boost::posix_time::ptime now(microsec_clock::universal_time()); - - do{ - if(this->try_wait()){ - break; - } - now = microsec_clock::universal_time(); - - if(now >= abs_time){ - return this->try_wait(); - } - // relinquish current time slice - ipcdetail::thread_yield(); - }while (true); - return true; + ipcdetail::lock_to_wait<spin_semaphore> lw(*this); + return ipcdetail::try_based_timed_lock(lw, abs_time); } - //inline int spin_semaphore::get_count() const //{ //return (int)ipcdetail::atomic_read32(&m_count); diff --git a/boost/interprocess/sync/spin/wait.hpp b/boost/interprocess/sync/spin/wait.hpp new file mode 100644 index 0000000000..220699bae1 --- /dev/null +++ b/boost/interprocess/sync/spin/wait.hpp @@ -0,0 +1,181 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Peter Dimov 2008. +// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +//Parts of this file come from boost/smart_ptr/detail/yield_k.hpp +//Many thanks to Peter Dimov. + +#ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED +#define BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED + +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/detail/os_thread_functions.hpp> + +//#define BOOST_INTERPROCESS_SPIN_WAIT_DEBUG +#ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG +#include <iostream> +#endif + +// BOOST_INTERPROCESS_SMT_PAUSE + +#if defined(_MSC_VER) && ( defined(_M_IX86) || defined(_M_X64) ) + +extern "C" void _mm_pause(); +#pragma intrinsic( _mm_pause ) + +#define BOOST_INTERPROCESS_SMT_PAUSE _mm_pause(); + +#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) && !defined(_CRAYC) + +#define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" ); + +#endif + +namespace boost{ +namespace interprocess{ +namespace ipcdetail { + +template<int Dummy = 0> +class num_core_holder +{ + public: + static unsigned int get() + { + if(!num_cores){ + return ipcdetail::get_num_cores(); + } + else{ + return num_cores; + } + } + + private: + static unsigned int num_cores; +}; + +template<int Dummy> +unsigned int num_core_holder<Dummy>::num_cores = ipcdetail::get_num_cores(); + +} //namespace ipcdetail { + +class spin_wait +{ + public: + + static const unsigned int nop_pause_limit = 32u; + spin_wait() + : m_count_start(), m_ul_yield_only_counts(), m_k() + {} + + #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG + ~spin_wait() + { + if(m_k){ + std::cout << "final m_k: " << m_k + << " system tick(us): " << ipcdetail::get_system_tick_us() << std::endl; + } + } + #endif + + unsigned int count() const + { return m_k; } + + void yield() + { + //Lazy initialization of limits + if( !m_k){ + this->init_limits(); + } + //Nop tries + if( m_k < (nop_pause_limit >> 2) ){ + + } + //Pause tries if the processor supports it + #if defined(BOOST_INTERPROCESS_SMT_PAUSE) + else if( m_k < nop_pause_limit ){ + BOOST_INTERPROCESS_SMT_PAUSE + } + #endif + //Yield/Sleep strategy + else{ + //Lazy initialization of tick information + if(m_k == nop_pause_limit){ + this->init_tick_info(); + } + else if( this->yield_or_sleep() ){ + ipcdetail::thread_yield(); + } + else{ + ipcdetail::thread_sleep_tick(); + } + } + ++m_k; + } + + void reset() + { + m_k = 0u; + } + + private: + + void init_limits() + { + unsigned int num_cores = ipcdetail::num_core_holder<0>::get(); + m_k = num_cores > 1u ? 0u : nop_pause_limit; + } + + void init_tick_info() + { + m_ul_yield_only_counts = ipcdetail::get_system_tick_in_highres_counts(); + m_count_start = ipcdetail::get_current_system_highres_count(); + } + + //Returns true if yield must be called, false is sleep must be called + bool yield_or_sleep() + { + if(!m_ul_yield_only_counts){ //If yield-only limit was reached then yield one in every two tries + return (m_k & 1u) != 0; + } + else{ //Try to see if we've reched yield-only time limit + const ipcdetail::OS_highres_count_t now = ipcdetail::get_current_system_highres_count(); + const ipcdetail::OS_highres_count_t elapsed = ipcdetail::system_highres_count_subtract(now, m_count_start); + if(!ipcdetail::system_highres_count_less_ul(elapsed, m_ul_yield_only_counts)){ + #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG + std::cout << "elapsed!\n" + << " m_ul_yield_only_counts: " << m_ul_yield_only_counts + << " system tick(us): " << ipcdetail::get_system_tick_us() << '\n' + << " m_k: " << m_k << " elapsed counts: "; + ipcdetail::ostream_highres_count(std::cout, elapsed) << std::endl; + #endif + //Yield-only time reached, now it's time to sleep + m_ul_yield_only_counts = 0ul; + return false; + } + } + return true; //Otherwise yield + } + + ipcdetail::OS_highres_count_t m_count_start; + unsigned long m_ul_yield_only_counts; + unsigned int m_k; +}; + +} // namespace interprocess +} // namespace boost + +#include <boost/interprocess/detail/config_end.hpp> + +#endif // #ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED diff --git a/boost/interprocess/sync/upgradable_lock.hpp b/boost/interprocess/sync/upgradable_lock.hpp index fb86374ca1..646019b433 100644 --- a/boost/interprocess/sync/upgradable_lock.hpp +++ b/boost/interprocess/sync/upgradable_lock.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -16,7 +16,7 @@ #ifndef BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP #define BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -28,7 +28,7 @@ #include <boost/interprocess/detail/type_traits.hpp> #include <boost/interprocess/exceptions.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> //!\file @@ -52,13 +52,13 @@ class upgradable_lock { public: typedef UpgradableMutex mutex_type; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef upgradable_lock<UpgradableMutex> this_type; explicit upgradable_lock(scoped_lock<mutex_type>&); typedef bool this_type::*unspecified_bool_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(upgradable_lock) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Effects: Default constructs a upgradable_lock. @@ -207,7 +207,7 @@ class upgradable_lock //!Notes: The sharable_lock changes from a state of not owning the mutex, //! to owning the mutex, blocking if necessary. void lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); mp_mutex->lock_upgradable(); @@ -223,7 +223,7 @@ class upgradable_lock //! mutex_type does not support try_lock_upgradable(), this function will //! fail at compile time if instantiated, but otherwise have no effect. bool try_lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->try_lock_upgradable(); @@ -240,7 +240,7 @@ class upgradable_lock //! timed_lock_upgradable(abs_time), this function will fail at compile //! time if instantiated, but otherwise have no effect. bool timed_lock(const boost::posix_time::ptime& abs_time) - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->timed_lock_upgradable(abs_time); @@ -294,11 +294,11 @@ class upgradable_lock std::swap(m_locked, other.m_locked); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: mutex_type *mp_mutex; bool m_locked; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; } // namespace interprocess diff --git a/boost/interprocess/sync/windows/condition.hpp b/boost/interprocess/sync/windows/condition.hpp index 9695c21044..d5b77c7efe 100644 --- a/boost/interprocess/sync/windows/condition.hpp +++ b/boost/interprocess/sync/windows/condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP #define BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> @@ -33,63 +37,38 @@ class windows_condition windows_condition &operator=(const windows_condition &); public: - windows_condition(); - ~windows_condition(); + windows_condition() + : m_condition_data() + {} + + ~windows_condition() + { + //Notify all waiting threads + //to allow POSIX semantics on condition destruction + this->notify_all(); + } + + void notify_one() + { m_condition_data.notify_one(); } - void notify_one(); - void notify_all(); + void notify_all() + { m_condition_data.notify_all(); } template <typename L> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) - { - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock); - return true; - } - if (!lock) - throw lock_exception(); - return this->do_timed_wait(abs_time, *lock.mutex()); - } + { return m_condition_data.timed_wait(lock, abs_time); } template <typename L, typename Pr> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) - { - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock, pred); - return true; - } - if (!lock) - throw lock_exception(); - while (!pred()){ - if (!this->do_timed_wait(abs_time, *lock.mutex())) - return pred(); - } - return true; - } + { return m_condition_data.timed_wait(lock, abs_time, pred); } template <typename L> void wait(L& lock) - { - if (!lock) - throw lock_exception(); - do_wait(*lock.mutex()); - } + { m_condition_data.wait(lock); } template <typename L, typename Pr> void wait(L& lock, Pr pred) - { - if (!lock) - throw lock_exception(); - - while (!pred()) - do_wait(*lock.mutex()); - } - - template<class InterprocessMutex> - void do_wait(InterprocessMutex &mut); - - template<class InterprocessMutex> - bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex &mut); + { m_condition_data.wait(lock, pred); } private: @@ -132,33 +111,11 @@ class windows_condition windows_semaphore m_sem_block_queue; windows_semaphore m_sem_block_lock; windows_mutex m_mtx_unblock_lock; - } m_condition_data; + }; - typedef condition_algorithm_8a<condition_data> algorithm_type; + ipcdetail::condition_8a_wrapper<condition_data> m_condition_data; }; -inline windows_condition::windows_condition() - : m_condition_data() -{} - -inline windows_condition::~windows_condition() -{} - -inline void windows_condition::notify_one() -{ algorithm_type::signal(m_condition_data, false); } - -inline void windows_condition::notify_all() -{ algorithm_type::signal(m_condition_data, true); } - -template<class InterprocessMutex> -inline void windows_condition::do_wait(InterprocessMutex &mut) -{ algorithm_type::wait(m_condition_data, false, boost::posix_time::ptime(), mut); } - -template<class InterprocessMutex> -inline bool windows_condition::do_timed_wait - (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut) -{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); } - } //namespace ipcdetail } //namespace interprocess } //namespace boost diff --git a/boost/interprocess/sync/windows/mutex.hpp b/boost/interprocess/sync/windows/mutex.hpp index 477acd396a..0b1958cfb7 100644 --- a/boost/interprocess/sync/windows/mutex.hpp +++ b/boost/interprocess/sync/windows/mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP #define BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -57,8 +57,8 @@ inline windows_mutex::windows_mutex() bool open_or_created; (void)handles.obtain_mutex(this->id_, &open_or_created); //The mutex must be created, never opened - assert(open_or_created); - assert(open_or_created && winapi::get_last_error() != winapi::error_already_exists); + BOOST_ASSERT(open_or_created); + BOOST_ASSERT(open_or_created && winapi::get_last_error() != winapi::error_already_exists); (void)open_or_created; } diff --git a/boost/interprocess/sync/windows/named_condition.hpp b/boost/interprocess/sync/windows/named_condition.hpp index 403e826178..ba220fdc5b 100644 --- a/boost/interprocess/sync/windows/named_condition.hpp +++ b/boost/interprocess/sync/windows/named_condition.hpp @@ -11,319 +11,19 @@ #ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP #define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> -#include <boost/interprocess/creation_tags.hpp> -#include <boost/interprocess/permissions.hpp> -#include <boost/interprocess/detail/interprocess_tester.hpp> -#include <boost/interprocess/detail/posix_time_types_wrk.hpp> -#include <boost/interprocess/sync/windows/named_sync.hpp> -#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp> -#include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp> +#include <boost/interprocess/sync/windows/named_condition_any.hpp> namespace boost { namespace interprocess { namespace ipcdetail { -class windows_named_condition -{ - /// @cond - - //Non-copyable - windows_named_condition(); - windows_named_condition(const windows_named_condition &); - windows_named_condition &operator=(const windows_named_condition &); - /// @endcond - - public: - windows_named_condition(create_only_t, const char *name, const permissions &perm = permissions()); - - windows_named_condition(open_or_create_t, const char *name, const permissions &perm = permissions()); - - windows_named_condition(open_only_t, const char *name); - - ~windows_named_condition(); - - //!If there is a thread waiting on *this, change that - //!thread's state to ready. Otherwise there is no effect.*/ - void notify_one(); - - //!Change the state of all threads waiting on *this to ready. - //!If there are no waiting threads, notify_all() has no effect. - void notify_all(); - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), and then reacquires the lock. - template <typename L> - void wait(L& lock); - - //!The same as: - //!while (!pred()) wait(lock) - template <typename L, typename Pr> - void wait(L& lock, Pr pred); - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), or until time abs_time is reached, - //!and then reacquires the lock. - //!Returns: false if time abs_time is reached, otherwise true. - template <typename L> - bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time); - - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); - //! } return true; - template <typename L, typename Pr> - bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred); - - static bool remove(const char *name); - - /// @cond - private: - friend class interprocess_tester; - void dont_close_on_destruction(); - - template <class InterprocessMutex> - void do_wait(InterprocessMutex& lock); - - template <class InterprocessMutex> - bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex& lock); - - struct condition_data - { - typedef boost::int32_t integer_type; - typedef winapi_semaphore_wrapper semaphore_type; - typedef winapi_mutex_wrapper mutex_type; - - integer_type &get_nwaiters_blocked() - { return m_nwaiters_blocked; } - - integer_type &get_nwaiters_gone() - { return m_nwaiters_gone; } - - integer_type &get_nwaiters_to_unblock() - { return m_nwaiters_to_unblock; } - - semaphore_type &get_sem_block_queue() - { return m_sem_block_queue; } - - semaphore_type &get_sem_block_lock() - { return m_sem_block_lock; } - - mutex_type &get_mtx_unblock_lock() - { return m_mtx_unblock_lock; } - - integer_type m_nwaiters_blocked; - integer_type m_nwaiters_gone; - integer_type m_nwaiters_to_unblock; - winapi_semaphore_wrapper m_sem_block_queue; - winapi_semaphore_wrapper m_sem_block_lock; - winapi_mutex_wrapper m_mtx_unblock_lock; - } m_condition_data; - - typedef condition_algorithm_8a<condition_data> algorithm_type; - - class named_cond_callbacks : public windows_named_sync_interface - { - typedef __int64 sem_count_t; - mutable sem_count_t sem_counts [2]; - - public: - named_cond_callbacks(condition_data &cond_data) - : m_condition_data(cond_data) - {} - - virtual std::size_t get_data_size() const - { return sizeof(sem_counts); } - - virtual const void *buffer_with_final_data_to_file() - { - sem_counts[0] = m_condition_data.m_sem_block_queue.value(); - sem_counts[1] = m_condition_data.m_sem_block_lock.value(); - return &sem_counts; - } - - virtual const void *buffer_with_init_data_to_file() - { - sem_counts[0] = 0; - sem_counts[1] = 1; - return &sem_counts; - } - - virtual void *buffer_to_store_init_data_from_file() - { return &sem_counts; } - - virtual bool open(create_enum_t, const char *id_name) - { - m_condition_data.m_nwaiters_blocked = 0; - m_condition_data.m_nwaiters_gone = 0; - m_condition_data.m_nwaiters_to_unblock = 0; - - //Now open semaphores and mutex. - //Use local variables + swap to guarantee consistent - //initialization and cleanup in case any opening fails - permissions perm; - perm.set_unrestricted(); - std::string aux_str = "Global\\bipc.cond."; - aux_str += id_name; - std::size_t pos = aux_str.size(); - - //sem_block_queue - aux_str += "_bq"; - winapi_semaphore_wrapper sem_block_queue; - bool created; - if(!sem_block_queue.open_or_create - (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created)) - return false; - aux_str.erase(pos); - - //sem_block_lock - aux_str += "_bl"; - winapi_semaphore_wrapper sem_block_lock; - if(!sem_block_lock.open_or_create - (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created)) - return false; - aux_str.erase(pos); - - //mtx_unblock_lock - aux_str += "_ul"; - winapi_mutex_wrapper mtx_unblock_lock; - if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm)) - return false; - - //All ok, commit data - m_condition_data.m_sem_block_queue.swap(sem_block_queue); - m_condition_data.m_sem_block_lock.swap(sem_block_lock); - m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock); - return true; - } - - virtual void close() - { - m_condition_data.m_sem_block_queue.close(); - m_condition_data.m_sem_block_lock.close(); - m_condition_data.m_mtx_unblock_lock.close(); - m_condition_data.m_nwaiters_blocked = 0; - m_condition_data.m_nwaiters_gone = 0; - m_condition_data.m_nwaiters_to_unblock = 0; - } - - virtual ~named_cond_callbacks() - {} - - private: - condition_data &m_condition_data; - }; - - windows_named_sync m_named_sync; - /// @endcond -}; - -inline windows_named_condition::~windows_named_condition() -{ - named_cond_callbacks callbacks(m_condition_data); - m_named_sync.close(callbacks); -} - -inline void windows_named_condition::dont_close_on_destruction() -{} - -inline windows_named_condition::windows_named_condition - (create_only_t, const char *name, const permissions &perm) - : m_condition_data() -{ - named_cond_callbacks callbacks(m_condition_data); - m_named_sync.open_or_create(DoCreate, name, perm, callbacks); -} - -inline windows_named_condition::windows_named_condition - (open_or_create_t, const char *name, const permissions &perm) - : m_condition_data() -{ - named_cond_callbacks callbacks(m_condition_data); - m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); -} - -inline windows_named_condition::windows_named_condition(open_only_t, const char *name) - : m_condition_data() -{ - named_cond_callbacks callbacks(m_condition_data); - m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); -} - -inline void windows_named_condition::notify_one() -{ algorithm_type::signal(m_condition_data, false); } - -inline void windows_named_condition::notify_all() -{ algorithm_type::signal(m_condition_data, true); } - -template<class InterprocessMutex> -inline void windows_named_condition::do_wait(InterprocessMutex &mut) -{ algorithm_type::wait(m_condition_data, false, boost::posix_time::ptime(), mut); } - -template<class InterprocessMutex> -inline bool windows_named_condition::do_timed_wait - (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut) -{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); } - -template <typename L> -inline void windows_named_condition::wait(L& lock) -{ - if (!lock) - throw lock_exception(); - this->do_wait(*lock.mutex()); -} - -template <typename L, typename Pr> -inline void windows_named_condition::wait(L& lock, Pr pred) -{ - if (!lock) - throw lock_exception(); - while (!pred()) - this->do_wait(*lock.mutex()); -} - -template <typename L> -inline bool windows_named_condition::timed_wait - (L& lock, const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock); - return true; - } - if (!lock) - throw lock_exception(); - return this->do_timed_wait(abs_time, *lock.mutex()); -} - -template <typename L, typename Pr> -inline bool windows_named_condition::timed_wait - (L& lock, const boost::posix_time::ptime &abs_time, Pr pred) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock, pred); - return true; - } - if (!lock) - throw lock_exception(); - - while (!pred()){ - if(!this->do_timed_wait(abs_time, *lock.mutex())){ - return pred(); - } - } - return true; -} - -inline bool windows_named_condition::remove(const char *name) -{ - return windows_named_sync::remove(name); -} +typedef windows_named_condition_any windows_named_condition; } //namespace ipcdetail { } //namespace interprocess { diff --git a/boost/interprocess/sync/windows/named_condition_any.hpp b/boost/interprocess/sync/windows/named_condition_any.hpp new file mode 100644 index 0000000000..fc2a7fce61 --- /dev/null +++ b/boost/interprocess/sync/windows/named_condition_any.hpp @@ -0,0 +1,240 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/creation_tags.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/detail/interprocess_tester.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/windows/named_sync.hpp> +#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp> +#include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class windows_named_condition_any +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Non-copyable + windows_named_condition_any(); + windows_named_condition_any(const windows_named_condition_any &); + windows_named_condition_any &operator=(const windows_named_condition_any &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + windows_named_condition_any + (create_only_t, const char *name, const permissions &perm) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); + } + + windows_named_condition_any + (open_or_create_t, const char *name, const permissions &perm) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); + } + + windows_named_condition_any(open_only_t, const char *name) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); + } + + ~windows_named_condition_any() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.close(callbacks); + } + + void notify_one() + { m_condition_data.notify_one(); } + + void notify_all() + { m_condition_data.notify_all(); } + + template <typename L> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { return m_condition_data.timed_wait(lock, abs_time); } + + template <typename L, typename Pr> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { return m_condition_data.timed_wait(lock, abs_time, pred); } + + template <typename L> + void wait(L& lock) + { m_condition_data.wait(lock); } + + template <typename L, typename Pr> + void wait(L& lock, Pr pred) + { m_condition_data.wait(lock, pred); } + + static bool remove(const char *name) + { return windows_named_sync::remove(name); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + void dont_close_on_destruction() + {} + + friend class interprocess_tester; + + struct condition_data + { + typedef boost::int32_t integer_type; + typedef winapi_semaphore_wrapper semaphore_type; + typedef winapi_mutex_wrapper mutex_type; + + integer_type &get_nwaiters_blocked() + { return m_nwaiters_blocked; } + + integer_type &get_nwaiters_gone() + { return m_nwaiters_gone; } + + integer_type &get_nwaiters_to_unblock() + { return m_nwaiters_to_unblock; } + + semaphore_type &get_sem_block_queue() + { return m_sem_block_queue; } + + semaphore_type &get_sem_block_lock() + { return m_sem_block_lock; } + + mutex_type &get_mtx_unblock_lock() + { return m_mtx_unblock_lock; } + + integer_type m_nwaiters_blocked; + integer_type m_nwaiters_gone; + integer_type m_nwaiters_to_unblock; + winapi_semaphore_wrapper m_sem_block_queue; + winapi_semaphore_wrapper m_sem_block_lock; + winapi_mutex_wrapper m_mtx_unblock_lock; + }; + + class named_cond_callbacks : public windows_named_sync_interface + { + typedef __int64 sem_count_t; + mutable sem_count_t sem_counts [2]; + + public: + named_cond_callbacks(condition_data &cond_data) + : m_condition_data(cond_data) + {} + + virtual std::size_t get_data_size() const + { return sizeof(sem_counts); } + + virtual const void *buffer_with_final_data_to_file() + { + sem_counts[0] = m_condition_data.m_sem_block_queue.value(); + sem_counts[1] = m_condition_data.m_sem_block_lock.value(); + return &sem_counts; + } + + virtual const void *buffer_with_init_data_to_file() + { + sem_counts[0] = 0; + sem_counts[1] = 1; + return &sem_counts; + } + + virtual void *buffer_to_store_init_data_from_file() + { return &sem_counts; } + + virtual bool open(create_enum_t, const char *id_name) + { + m_condition_data.m_nwaiters_blocked = 0; + m_condition_data.m_nwaiters_gone = 0; + m_condition_data.m_nwaiters_to_unblock = 0; + + //Now open semaphores and mutex. + //Use local variables + swap to guarantee consistent + //initialization and cleanup in case any opening fails + permissions perm; + perm.set_unrestricted(); + std::string aux_str = "Global\\bipc.cond."; + aux_str += id_name; + std::size_t pos = aux_str.size(); + + //sem_block_queue + aux_str += "_bq"; + winapi_semaphore_wrapper sem_block_queue; + bool created; + if(!sem_block_queue.open_or_create + (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created)) + return false; + aux_str.erase(pos); + + //sem_block_lock + aux_str += "_bl"; + winapi_semaphore_wrapper sem_block_lock; + if(!sem_block_lock.open_or_create + (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created)) + return false; + aux_str.erase(pos); + + //mtx_unblock_lock + aux_str += "_ul"; + winapi_mutex_wrapper mtx_unblock_lock; + if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm)) + return false; + + //All ok, commit data + m_condition_data.m_sem_block_queue.swap(sem_block_queue); + m_condition_data.m_sem_block_lock.swap(sem_block_lock); + m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock); + return true; + } + + virtual void close() + { + m_condition_data.m_sem_block_queue.close(); + m_condition_data.m_sem_block_lock.close(); + m_condition_data.m_mtx_unblock_lock.close(); + m_condition_data.m_nwaiters_blocked = 0; + m_condition_data.m_nwaiters_gone = 0; + m_condition_data.m_nwaiters_to_unblock = 0; + } + + virtual ~named_cond_callbacks() + {} + + private: + condition_data &m_condition_data; + }; + + windows_named_sync m_named_sync; + ipcdetail::condition_8a_wrapper<condition_data> m_condition_data; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP diff --git a/boost/interprocess/sync/windows/named_mutex.hpp b/boost/interprocess/sync/windows/named_mutex.hpp index 8ea6b3e1e4..9d5738562b 100644 --- a/boost/interprocess/sync/windows/named_mutex.hpp +++ b/boost/interprocess/sync/windows/named_mutex.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP #define BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -35,13 +35,13 @@ namespace ipcdetail { class windows_named_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable windows_named_mutex(); windows_named_mutex(const windows_named_mutex &); windows_named_mutex &operator=(const windows_named_mutex &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: windows_named_mutex(create_only_t, const char *name, const permissions &perm = permissions()); @@ -59,7 +59,7 @@ class windows_named_mutex static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class interprocess_tester; void dont_close_on_destruction(); @@ -106,7 +106,7 @@ class windows_named_mutex private: winapi_mutex_wrapper& m_mtx_wrapper; }; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; inline windows_named_mutex::~windows_named_mutex() diff --git a/boost/interprocess/sync/windows/named_recursive_mutex.hpp b/boost/interprocess/sync/windows/named_recursive_mutex.hpp index cb2ef79ac1..695c44a5a9 100644 --- a/boost/interprocess/sync/windows/named_recursive_mutex.hpp +++ b/boost/interprocess/sync/windows/named_recursive_mutex.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP #define BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -27,13 +27,13 @@ class windows_named_recursive_mutex //Windows mutexes based on CreateMutex are already recursive... : public windows_named_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable windows_named_recursive_mutex(); windows_named_recursive_mutex(const windows_named_mutex &); windows_named_recursive_mutex &operator=(const windows_named_mutex &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: windows_named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions()) diff --git a/boost/interprocess/sync/windows/named_semaphore.hpp b/boost/interprocess/sync/windows/named_semaphore.hpp index 8f48d4df96..7adf91b751 100644 --- a/boost/interprocess/sync/windows/named_semaphore.hpp +++ b/boost/interprocess/sync/windows/named_semaphore.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP #define BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -32,13 +32,13 @@ namespace ipcdetail { class windows_named_semaphore { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable windows_named_semaphore(); windows_named_semaphore(const windows_named_semaphore &); windows_named_semaphore &operator=(const windows_named_semaphore &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: windows_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); @@ -56,7 +56,7 @@ class windows_named_semaphore static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class interprocess_tester; void dont_close_on_destruction(); @@ -109,7 +109,7 @@ class windows_named_semaphore winapi_semaphore_wrapper& m_sem_wrapper; }; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; inline windows_named_semaphore::~windows_named_semaphore() diff --git a/boost/interprocess/sync/windows/named_sync.hpp b/boost/interprocess/sync/windows/named_sync.hpp index 41f299f8eb..5af7a3221a 100644 --- a/boost/interprocess/sync/windows/named_sync.hpp +++ b/boost/interprocess/sync/windows/named_sync.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP #define BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -19,12 +19,12 @@ #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/permissions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #include <boost/interprocess/sync/windows/sync_utils.hpp> #include <boost/interprocess/errors.hpp> #include <boost/interprocess/exceptions.hpp> #include <string> -#include <cassert> +#include <boost/assert.hpp> namespace boost { namespace interprocess { @@ -47,12 +47,12 @@ inline windows_named_sync_interface::~windows_named_sync_interface() class windows_named_sync { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable windows_named_sync(const windows_named_sync &); windows_named_sync &operator=(const windows_named_sync &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: windows_named_sync(); @@ -61,11 +61,11 @@ class windows_named_sync static bool remove(const char *name); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: void *m_file_hnd; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; inline windows_named_sync::windows_named_sync() @@ -106,7 +106,7 @@ inline void windows_named_sync::open_or_create //Use a file to emulate POSIX lifetime semantics. After this logic //we'll obtain the ID of the native handle to open in aux_str { - create_tmp_and_clean_old_and_get_filename(name, aux_str); + create_shared_dir_cleaning_old_and_get_filepath(name, aux_str); //Create a file with required permissions. m_file_hnd = winapi::create_file ( aux_str.c_str() @@ -145,7 +145,7 @@ inline void windows_named_sync::open_or_create success = true; } winapi::get_file_size(m_file_hnd, filesize); - assert(std::size_t(filesize) == sizeof_file_info); + BOOST_ASSERT(std::size_t(filesize) == sizeof_file_info); } else{ void *buf = sync_interface.buffer_to_store_init_data_from_file(); @@ -198,7 +198,7 @@ inline bool windows_named_sync::remove(const char *name) try{ //Make sure a temporary path is created for shared memory std::string semfile; - ipcdetail::tmp_filename(name, semfile); + ipcdetail::shared_filepath(name, semfile); return winapi::unlink_file(semfile.c_str()); } catch(...){ diff --git a/boost/interprocess/sync/windows/recursive_mutex.hpp b/boost/interprocess/sync/windows/recursive_mutex.hpp index 9565cb6fb4..55a838583b 100644 --- a/boost/interprocess/sync/windows/recursive_mutex.hpp +++ b/boost/interprocess/sync/windows/recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP #define BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/sync/windows/semaphore.hpp b/boost/interprocess/sync/windows/semaphore.hpp index af336df48a..7fdbc41b3d 100644 --- a/boost/interprocess/sync/windows/semaphore.hpp +++ b/boost/interprocess/sync/windows/semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP #define BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -23,6 +23,7 @@ #include <boost/interprocess/sync/windows/sync_utils.hpp> #include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp> #include <boost/interprocess/exceptions.hpp> +#include <boost/assert.hpp> namespace boost { @@ -56,8 +57,8 @@ inline windows_semaphore::windows_semaphore(unsigned int initialCount) bool open_or_created; handles.obtain_semaphore(this->id_, initialCount, &open_or_created); //The semaphore must be created, never opened - assert(open_or_created); - assert(open_or_created && winapi::get_last_error() != winapi::error_already_exists); + BOOST_ASSERT(open_or_created); + BOOST_ASSERT(open_or_created && winapi::get_last_error() != winapi::error_already_exists); (void)open_or_created; } diff --git a/boost/interprocess/sync/windows/sync_utils.hpp b/boost/interprocess/sync/windows/sync_utils.hpp index 0281da1266..7e54cc36b2 100644 --- a/boost/interprocess/sync/windows/sync_utils.hpp +++ b/boost/interprocess/sync/windows/sync_utils.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP #define BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -23,7 +23,13 @@ #include <boost/interprocess/sync/scoped_lock.hpp> #include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp> #include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp> -#include <boost/unordered/unordered_map.hpp> + +//Shield against external warnings +#include <boost/interprocess/detail/config_external_begin.hpp> + #include <boost/unordered/unordered_map.hpp> +#include <boost/interprocess/detail/config_external_end.hpp> + + #include <boost/container/map.hpp> #include <cstddef> @@ -71,7 +77,7 @@ class sync_id internal_type &internal_pod() { return rand_; } - const void *map_addr() const + const void *map_address() const { return map_addr_; } friend std::size_t hash_value(const sync_id &m) @@ -94,7 +100,7 @@ class sync_handles struct address_less { bool operator()(sync_id const * const l, sync_id const * const r) const - { return l->map_addr() < r->map_addr(); } + { return l->map_address() < r->map_address(); } }; typedef boost::unordered_map<sync_id, void*> umap_type; @@ -156,12 +162,15 @@ class sync_handles umap_type::value_type v(id, (void*)0); scoped_lock<spin_mutex> lock(mtx_); umap_type::iterator it = umap_.insert(v).first; - map_[&it->first] = it; void *&hnd_val = it->second; if(!hnd_val){ + map_[&it->first] = it; hnd_val = open_or_create_mutex(id); if(popen_created) *popen_created = true; } + else if(popen_created){ + *popen_created = false; + } return hnd_val; } @@ -170,12 +179,15 @@ class sync_handles umap_type::value_type v(id, (void*)0); scoped_lock<spin_mutex> lock(mtx_); umap_type::iterator it = umap_.insert(v).first; - map_[&it->first] = it; void *&hnd_val = it->second; if(!hnd_val){ + map_[&it->first] = it; hnd_val = open_or_create_semaphore(id, initial_count); if(popen_created) *popen_created = true; } + else if(popen_created){ + *popen_created = false; + } return hnd_val; } @@ -195,13 +207,13 @@ class sync_handles void destroy_syncs_in_range(const void *addr, std::size_t size) { - sync_id low_id(addr); - sync_id hig_id(static_cast<const char*>(addr)+size); + const sync_id low_id(addr); + const sync_id hig_id(static_cast<const char*>(addr)+size); scoped_lock<spin_mutex> lock(mtx_); map_type::iterator itlow(map_.lower_bound(&low_id)), ithig(map_.lower_bound(&hig_id)); while(itlow != ithig){ - void *hnd = umap_[*itlow->first]; + void * const hnd = umap_[*itlow->first]; winapi::close_handle(hnd); umap_.erase(*itlow->first); itlow = map_.erase(itlow); diff --git a/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp b/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp index 0be96011cf..f7b78a9260 100644 --- a/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp +++ b/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP #define BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -21,6 +21,7 @@ #include <boost/interprocess/permissions.hpp> #include <boost/interprocess/detail/win32_api.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/windows/winapi_wrapper_common.hpp> #include <boost/interprocess/errors.hpp> #include <boost/interprocess/exceptions.hpp> #include <limits> @@ -31,12 +32,12 @@ namespace ipcdetail { class winapi_mutex_functions { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable winapi_mutex_functions(const winapi_mutex_functions &); winapi_mutex_functions &operator=(const winapi_mutex_functions &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: winapi_mutex_functions(void *mtx_hnd) @@ -44,73 +45,39 @@ class winapi_mutex_functions {} void unlock() - { - winapi::release_mutex(m_mtx_hnd); - } + { winapi::release_mutex(m_mtx_hnd); } void lock() - { - if(winapi::wait_for_single_object(m_mtx_hnd, winapi::infinite_time) != winapi::wait_object_0){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - } + { return winapi_wrapper_wait_for_single_object(m_mtx_hnd); } bool try_lock() - { - unsigned long ret = winapi::wait_for_single_object(m_mtx_hnd, 0); - if(ret == winapi::wait_object_0){ - return true; - } - else if(ret == winapi::wait_timeout){ - return false; - } - else{ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - } + { return winapi_wrapper_try_wait_for_single_object(m_mtx_hnd); } bool timed_lock(const boost::posix_time::ptime &abs_time) - { - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } + { return winapi_wrapper_timed_wait_for_single_object(m_mtx_hnd, abs_time); } - unsigned long ret = winapi::wait_for_single_object - (m_mtx_hnd, (abs_time - microsec_clock::universal_time()).total_milliseconds()); - if(ret == winapi::wait_object_0){ - return true; - } - else if(ret == winapi::wait_timeout){ - return false; - } - else{ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - } - - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) protected: void *m_mtx_hnd; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //Swappable mutex wrapper class winapi_mutex_wrapper : public winapi_mutex_functions { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable winapi_mutex_wrapper(const winapi_mutex_wrapper &); winapi_mutex_wrapper &operator=(const winapi_mutex_wrapper &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //Note that Windows API does not return winapi::invalid_handle_value + //when failing to create/open a mutex, but a nullptr public: - winapi_mutex_wrapper(void *mtx_hnd = winapi::invalid_handle_value) + winapi_mutex_wrapper(void *mtx_hnd = 0) : winapi_mutex_functions(mtx_hnd) {} @@ -120,7 +87,7 @@ class winapi_mutex_wrapper void *release() { void *hnd = m_mtx_hnd; - m_mtx_hnd = winapi::invalid_handle_value; + m_mtx_hnd = 0; return hnd; } @@ -129,24 +96,24 @@ class winapi_mutex_wrapper bool open_or_create(const char *name, const permissions &perm) { - if(m_mtx_hnd == winapi::invalid_handle_value){ + if(m_mtx_hnd == 0){ m_mtx_hnd = winapi::open_or_create_mutex ( name , false , (winapi::interprocess_security_attributes*)perm.get_permissions() ); - return m_mtx_hnd != winapi::invalid_handle_value; + return m_mtx_hnd != 0; } else{ return false; } - } + } void close() { - if(m_mtx_hnd != winapi::invalid_handle_value){ + if(m_mtx_hnd != 0){ winapi::close_handle(m_mtx_hnd); - m_mtx_hnd = winapi::invalid_handle_value; + m_mtx_hnd = 0; } } diff --git a/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp b/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp index 2dd7845627..f64d506d4d 100644 --- a/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp +++ b/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP #define BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -21,6 +21,7 @@ #include <boost/interprocess/permissions.hpp> #include <boost/interprocess/detail/win32_api.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/windows/winapi_wrapper_common.hpp> #include <boost/interprocess/errors.hpp> #include <boost/interprocess/exceptions.hpp> #include <limits> @@ -31,12 +32,12 @@ namespace ipcdetail { class winapi_semaphore_functions { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable winapi_semaphore_functions(const winapi_semaphore_functions &); winapi_semaphore_functions &operator=(const winapi_semaphore_functions &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: winapi_semaphore_functions(void *hnd) @@ -50,69 +51,34 @@ class winapi_semaphore_functions } void wait() - { - if(winapi::wait_for_single_object(m_sem_hnd, winapi::infinite_time) != winapi::wait_object_0){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - } + { return winapi_wrapper_wait_for_single_object(m_sem_hnd); } bool try_wait() - { - unsigned long ret = winapi::wait_for_single_object(m_sem_hnd, 0); - if(ret == winapi::wait_object_0){ - return true; - } - else if(ret == winapi::wait_timeout){ - return false; - } - else{ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - } + { return winapi_wrapper_try_wait_for_single_object(m_sem_hnd); } bool timed_wait(const boost::posix_time::ptime &abs_time) - { - if(abs_time == boost::posix_time::pos_infin){ - this->wait(); - return true; - } - - unsigned long ret = winapi::wait_for_single_object - (m_sem_hnd, (abs_time - microsec_clock::universal_time()).total_milliseconds()); - if(ret == winapi::wait_object_0){ - return true; - } - else if(ret == winapi::wait_timeout){ - return false; - } - else{ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - } + { return winapi_wrapper_timed_wait_for_single_object(m_sem_hnd, abs_time); } long value() const { - long count, limit; - if(!winapi::get_semaphore_info(m_sem_hnd, count, limit)) + long l_count, l_limit; + if(!winapi::get_semaphore_info(m_sem_hnd, l_count, l_limit)) return 0; - return count; + return l_count; } long limit() const { - long count, limit; - if(!winapi::get_semaphore_info(m_sem_hnd, count, limit)) + long l_count, l_limit; + if(!winapi::get_semaphore_info(m_sem_hnd, l_count, l_limit)) return 0; - return limit; + return l_limit; } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) protected: void *m_sem_hnd; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; @@ -136,7 +102,7 @@ class winapi_semaphore_wrapper { this->close(); } void *release() - { + { void *hnd = m_sem_hnd; m_sem_hnd = winapi::invalid_handle_value; return hnd; diff --git a/boost/interprocess/sync/windows/winapi_wrapper_common.hpp b/boost/interprocess/sync/windows/winapi_wrapper_common.hpp new file mode 100644 index 0000000000..ccf2d65cb6 --- /dev/null +++ b/boost/interprocess/sync/windows/winapi_wrapper_common.hpp @@ -0,0 +1,93 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_WINAPI_WRAPPER_COMMON_HPP +#define BOOST_INTERPROCESS_DETAIL_WINAPI_WRAPPER_COMMON_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/detail/win32_api.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/errors.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <limits> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +inline void winapi_wrapper_wait_for_single_object(void *handle) +{ + unsigned long ret = winapi::wait_for_single_object(handle, winapi::infinite_time); + if(ret != winapi::wait_object_0){ + if(ret != winapi::wait_abandoned){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + else{ //Special case for orphaned mutexes + winapi::release_mutex(handle); + throw interprocess_exception(owner_dead_error); + } + } +} + +inline bool winapi_wrapper_try_wait_for_single_object(void *handle) +{ + unsigned long ret = winapi::wait_for_single_object(handle, 0); + if(ret == winapi::wait_object_0){ + return true; + } + else if(ret == winapi::wait_timeout){ + return false; + } + else{ + error_info err = system_error_code(); + throw interprocess_exception(err); + } +} + +inline bool winapi_wrapper_timed_wait_for_single_object(void *handle, const boost::posix_time::ptime &abs_time) +{ + //Windows does not support infinity abs_time so check it + if(abs_time == boost::posix_time::pos_infin){ + winapi_wrapper_wait_for_single_object(handle); + return true; + } + const boost::posix_time::ptime cur_time = microsec_clock::universal_time(); + //Windows uses relative wait times so check for negative waits + //and implement as 0 wait to allow try-semantics as POSIX mandates. + unsigned long ret = winapi::wait_for_single_object + ( handle + , (abs_time <= cur_time) ? 0u + : (abs_time - cur_time).total_milliseconds() + ); + if(ret == winapi::wait_object_0){ + return true; + } + else if(ret == winapi::wait_timeout){ + return false; + } + else{ + error_info err = system_error_code(); + throw interprocess_exception(err); + } +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP diff --git a/boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp b/boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp index a0c3a91adf..b69cfbf934 100644 --- a/boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp +++ b/boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp @@ -30,6 +30,10 @@ #ifndef BOOST_INTERPROCESS_SYNC_XSI_ADVANCED_XSI_SEMAPHORE_HPP #define BOOST_INTERPROCESS_SYNC_XSI_ADVANCED_XSI_SEMAPHORE_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <sys/ipc.h> #include <sys/sem.h> #include <errno.h> diff --git a/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp b/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp index 266e7c5dac..69ad34caf2 100644 --- a/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp +++ b/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -10,6 +10,10 @@ #ifndef BOOST_INTERPROCESS_SYNC_XSI_SIMPLE_XSI_SEMAPHORE_HPP #define BOOST_INTERPROCESS_SYNC_XSI_SIMPLE_XSI_SEMAPHORE_HPP +#if defined(_MSC_VER) +# pragma once +#endif + /* * Provide an simpler and easier to understand interface to the System V * semaphore system calls. There are 7 routines available to the user: diff --git a/boost/interprocess/sync/xsi/xsi_named_mutex.hpp b/boost/interprocess/sync/xsi/xsi_named_mutex.hpp index 485b1ac101..1c4ee78a4f 100644 --- a/boost/interprocess/sync/xsi/xsi_named_mutex.hpp +++ b/boost/interprocess/sync/xsi/xsi_named_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP #define BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -18,7 +22,7 @@ #error "This header can't be used in Windows operating systems" #endif -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/detail/utilities.hpp> @@ -42,11 +46,11 @@ namespace interprocess { //!that undoes the operation if the process crashes. class xsi_named_mutex { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable and non-assignable xsi_named_mutex(xsi_named_mutex &); xsi_named_mutex &operator=(xsi_named_mutex &); - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_named_mutex) @@ -72,10 +76,10 @@ class xsi_named_mutex //!After the call, "moved" does not represent any named mutex. //!Does not throw xsi_named_mutex &operator=(BOOST_RV_REF(xsi_named_mutex) moved) - { + { xsi_named_mutex tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps two xsi_named_mutex. Does not throw @@ -105,7 +109,7 @@ class xsi_named_mutex void unlock(); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //!Closes a previously opened file mapping. Never throws. @@ -121,10 +125,10 @@ class xsi_named_mutex boost::uint8_t m_id; int m_perm; std::string m_path; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline xsi_named_mutex::xsi_named_mutex() : m_semid(-1), m_key(-1), m_id(0), m_perm(0), m_path() @@ -142,7 +146,7 @@ inline void xsi_named_mutex::swap(xsi_named_mutex &other) std::swap(m_id, other.m_id); std::swap(m_semid, other.m_semid); std::swap(m_perm, other.m_perm); - m_path.swap(other.m_path); + m_path.swap(other.m_path); } inline mapping_handle_t xsi_named_mutex::get_mapping_handle() const @@ -218,7 +222,7 @@ inline bool xsi_named_mutex::remove() return false; } -///@endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/windows_shared_memory.hpp b/boost/interprocess/windows_shared_memory.hpp index 76601bb363..5898b4b113 100644 --- a/boost/interprocess/windows_shared_memory.hpp +++ b/boost/interprocess/windows_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP #define BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/detail/workaround.hpp> @@ -50,23 +54,23 @@ namespace interprocess { //!can't communicate between them. class windows_shared_memory { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable and non-assignable BOOST_MOVABLE_BUT_NOT_COPYABLE(windows_shared_memory) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Default constructor. //!Represents an empty windows_shared_memory. windows_shared_memory(); - //!Creates a new native shared memory with name "name" and mode "mode", + //!Creates a new native shared memory with name "name" and at least size "size", //!with the access mode "mode". //!If the file previously exists, throws an error. windows_shared_memory(create_only_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, size, perm); } - //!Tries to create a shared memory object with name "name" and mode "mode", with the + //!Tries to create a shared memory object with name "name" and at least size "size", with the //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". //!Otherwise throws an error. windows_shared_memory(open_or_create_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) @@ -88,10 +92,10 @@ class windows_shared_memory //!After the call, "moved" does not represent any shared memory. //!Does not throw windows_shared_memory &operator=(BOOST_RV_REF(windows_shared_memory) moved) - { + { windows_shared_memory tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps to shared_memory_objects. Does not throw @@ -112,7 +116,11 @@ class windows_shared_memory //!Returns the mapping handle. Never throws mapping_handle_t get_mapping_handle() const; - /// @cond + //!Returns the size of the windows shared memory. It will be a 4K rounded + //!size of the "size" passed in the constructor. + offset_t get_size() const; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //!Closes a previously opened file mapping. Never throws. @@ -124,10 +132,10 @@ class windows_shared_memory void * m_handle; mode_t m_mode; std::string m_name; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline windows_shared_memory::windows_shared_memory() : m_handle(0) @@ -140,10 +148,10 @@ inline const char *windows_shared_memory::get_name() const { return m_name.c_str(); } inline void windows_shared_memory::swap(windows_shared_memory &other) -{ +{ std::swap(m_handle, other.m_handle); std::swap(m_mode, other.m_mode); - m_name.swap(other.m_name); + m_name.swap(other.m_name); } inline mapping_handle_t windows_shared_memory::get_mapping_handle() const @@ -152,6 +160,12 @@ inline mapping_handle_t windows_shared_memory::get_mapping_handle() const inline mode_t windows_shared_memory::get_mode() const { return m_mode; } +inline offset_t windows_shared_memory::get_size() const +{ + offset_t size; //This shall never fail + return (m_handle && winapi::get_file_mapping_size(m_handle, size)) ? size : 0; +} + inline bool windows_shared_memory::priv_open_or_create (ipcdetail::create_enum_t type, const char *filename, mode_t mode, std::size_t size, const permissions& perm) { @@ -223,7 +237,7 @@ inline void windows_shared_memory::priv_close() } } -///@endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/xsi_key.hpp b/boost/interprocess/xsi_key.hpp index ffd4c498df..38e990a57e 100644 --- a/boost/interprocess/xsi_key.hpp +++ b/boost/interprocess/xsi_key.hpp @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_XSI_KEY_HPP #define BOOST_INTERPROCESS_XSI_KEY_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/detail/workaround.hpp> @@ -22,7 +26,7 @@ #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/detail/utilities.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> #include <boost/interprocess/interprocess_fwd.hpp> #include <boost/interprocess/exceptions.hpp> @@ -55,7 +59,7 @@ class xsi_key //!If the shared memory previously exists, throws an error. xsi_key(const char *path, boost::uint8_t id) { - key_t key; + key_t key; if(path){ key = ::ftok(path, id); if(((key_t)-1) == key){ @@ -73,10 +77,10 @@ class xsi_key key_t get_key() const { return m_key; } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: key_t m_key; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; } //namespace interprocess { diff --git a/boost/interprocess/xsi_shared_memory.hpp b/boost/interprocess/xsi_shared_memory.hpp index e84d9b1c54..3451717d0b 100644 --- a/boost/interprocess/xsi_shared_memory.hpp +++ b/boost/interprocess/xsi_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_HPP #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/detail/workaround.hpp> @@ -22,7 +26,7 @@ #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/detail/utilities.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> #include <boost/interprocess/interprocess_fwd.hpp> #include <boost/interprocess/exceptions.hpp> @@ -47,10 +51,10 @@ namespace interprocess { //!can't communicate between them. class xsi_shared_memory { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Non-copyable and non-assignable BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Default constructor. @@ -89,10 +93,10 @@ class xsi_shared_memory //!After the call, "moved" does not represent any shared memory. //!Does not throw xsi_shared_memory &operator=(BOOST_RV_REF(xsi_shared_memory) moved) - { + { xsi_shared_memory tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps two xsi_shared_memorys. Does not throw @@ -115,7 +119,7 @@ class xsi_shared_memory //!Returns false on error. Never throws static bool remove(int shmid); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //!Closes a previously opened file mapping. Never throws. @@ -124,10 +128,10 @@ class xsi_shared_memory , const permissions& perm , std::size_t size); int m_shmid; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline xsi_shared_memory::xsi_shared_memory() : m_shmid(-1) @@ -191,7 +195,7 @@ inline bool xsi_shared_memory::priv_open_or_create inline bool xsi_shared_memory::remove(int shmid) { return -1 != ::shmctl(shmid, IPC_RMID, 0); } -///@endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { |