Changes for Boost.1.39

[SVN r52034]
This commit is contained in:
Ion Gaztañaga
2009-03-28 14:39:16 +00:00
114 changed files with 20819 additions and 17609 deletions

View File

@@ -18,6 +18,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
@@ -80,9 +82,9 @@ class adaptive_pool_base
public:
//-------
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -92,13 +94,9 @@ class adaptive_pool_base
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef detail::version_type<adaptive_pool_base, Version> version;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef boost::interprocess::version_type<adaptive_pool_base, Version> version;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
//!Obtains adaptive_pool_base from
//!adaptive_pool_base
@@ -266,7 +264,7 @@ class adaptive_pool
typedef detail::adaptive_pool_base
< 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
public:
typedef detail::version_type<adaptive_pool, 2> version;
typedef boost::interprocess::version_type<adaptive_pool, 2> version;
template<class T2>
struct rebind
@@ -388,7 +386,7 @@ class adaptive_pool
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -399,12 +397,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_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -412,7 +410,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_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -425,7 +423,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_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -438,7 +436,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_iterator it);
void deallocate_individual(multiallocation_chain it);
#endif
};

View File

@@ -18,15 +18,17 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/allocators/allocation_type.hpp>
#include <boost/interprocess/containers/allocation_type.hpp>
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/containers/version_type.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/iterators.hpp>
#include <memory>
#include <algorithm>
@@ -64,11 +66,11 @@ class allocator
//Typedef to const void pointer
typedef typename
detail::pointer_to_other
boost::pointer_to_other
<aux_pointer_t, const void>::type cvoid_ptr;
//Pointer to the allocator
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<cvoid_ptr, segment_manager>::type alloc_ptr_t;
//Not assignable from related allocator
@@ -84,9 +86,9 @@ class allocator
public:
typedef T value_type;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<cvoid_ptr, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<pointer, const T>::type const_pointer;
typedef typename detail::add_reference
<value_type>::type reference;
@@ -95,20 +97,13 @@ class allocator
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef detail::version_type<allocator, 2> version;
typedef boost::interprocess::version_type<allocator, 2> version;
/// @cond
//Experimental. Don't use.
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef detail::multiallocation_chain_adaptor
<typename SegmentManager::
multiallocation_chain
, T> multiallocation_chain;
typedef boost::interprocess::detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
/// @endcond
//!Obtains an allocator that allocates
@@ -174,7 +169,7 @@ class allocator
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0)
@@ -189,19 +184,19 @@ 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_iterator allocate_many(size_type elem_size, std::size_t num_elements)
multiallocation_chain allocate_many
(size_type elem_size, std::size_t num_elements)
{
return multiallocation_iterator
(mp_mngr->allocate_many(sizeof(T)*elem_size, num_elements));
return multiallocation_chain(mp_mngr->allocate_many(sizeof(T)*elem_size, num_elements));
}
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements)
multiallocation_chain allocate_many
(const size_type *elem_sizes, size_type n_elements)
{
return multiallocation_iterator
(mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T)));
multiallocation_chain(mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T)));
}
//!Allocates many elements of size elem_size in a contiguous block
@@ -210,8 +205,10 @@ 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_iterator it)
{ return mp_mngr->deallocate_many(it.base()); }
void deallocate_many(multiallocation_chain chain)
{
return mp_mngr->deallocate_many(chain.extract_multiallocation_chain());
}
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -225,7 +222,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_iterator allocate_individual(std::size_t num_elements)
multiallocation_chain allocate_individual
(std::size_t num_elements)
{ return this->allocate_many(1, num_elements); }
//!Deallocates memory previously allocated with allocate_one().
@@ -240,8 +238,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_iterator it)
{ return this->deallocate_many(it); }
void deallocate_individual(multiallocation_chain chain)
{ return this->deallocate_many(boost::interprocess::move(chain)); }
//!Returns address of mutable object.
//!Never throws

View File

@@ -23,7 +23,7 @@
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/containers/version_type.hpp>
#include <boost/interprocess/allocators/detail/node_tools.hpp>
#include <cstddef>
@@ -143,7 +143,7 @@ class cached_adaptive_pool
, 2> base_t;
public:
typedef detail::version_type<cached_adaptive_pool, 2> version;
typedef boost::interprocess::version_type<cached_adaptive_pool, 2> version;
template<class T2>
struct rebind
@@ -267,7 +267,7 @@ class cached_adaptive_pool
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -278,12 +278,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_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -291,7 +291,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_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -304,7 +304,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().
multiallocation_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -317,7 +317,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_iterator it);
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(std::size_t newmax);

View File

@@ -23,7 +23,7 @@
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/containers/version_type.hpp>
#include <boost/interprocess/allocators/detail/node_tools.hpp>
#include <cstddef>
@@ -115,7 +115,7 @@ class cached_node_allocator
, 2> base_t;
public:
typedef detail::version_type<cached_node_allocator, 2> version;
typedef boost::interprocess::version_type<cached_node_allocator, 2> version;
template<class T2>
struct rebind
@@ -238,7 +238,7 @@ class cached_node_allocator
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -249,12 +249,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_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -262,7 +262,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_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -275,7 +275,7 @@ class cached_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_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -288,7 +288,7 @@ class cached_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_iterator it);
void deallocate_individual(multiallocation_chain it);
//!Sets the new max cached nodes value. This can provoke deallocations
//!if "newmax" is less than current cached nodes. Never throws
void set_max_cached_nodes(std::size_t newmax);

View File

@@ -17,6 +17,7 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/detail/utilities.hpp>
@@ -27,6 +28,7 @@
#include <boost/intrusive/slist.hpp>
#include <boost/math/common_factor_ct.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
#include <boost/interprocess/allocators/detail/node_tools.hpp>
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
#include <cstddef>
@@ -53,7 +55,6 @@ class private_adaptive_node_pool_impl
public:
typedef typename node_slist<void_pointer>::node_t node_t;
typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
typedef typename SegmentManagerBase::multiallocation_iterator multiallocation_iterator;
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
private:
@@ -200,8 +201,9 @@ class private_adaptive_node_pool_impl
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *pElem)
{
this->priv_reinsert_nodes_in_block
(multiallocation_iterator::create_simple_range(pElem));
multiallocation_chain chain;
chain.push_front(void_pointer(pElem));
this->priv_reinsert_nodes_in_block(chain, 1);
//Update free block count
if(m_totally_free_blocks > m_max_free_blocks){
this->priv_deallocate_free_blocks(m_max_free_blocks);
@@ -209,13 +211,14 @@ class private_adaptive_node_pool_impl
priv_invariants();
}
//!Allocates a singly linked list of n nodes ending in null pointer.
//!can throw boost::interprocess::bad_alloc
void allocate_nodes(multiallocation_chain &nodes, const std::size_t n)
//!Allocates n nodes.
//!Can throw boost::interprocess::bad_alloc
multiallocation_chain allocate_nodes(const std::size_t n)
{
multiallocation_chain chain;
std::size_t i = 0;
try{
priv_invariants();
std::size_t i = 0;
while(i != n){
//If there are no free nodes we allocate all needed blocks
if (m_block_multiset.empty()){
@@ -230,9 +233,9 @@ class private_adaptive_node_pool_impl
for(std::size_t j = 0; j != num_elems; ++j){
void *new_node = &free_nodes.front();
free_nodes.pop_front();
nodes.push_back(new_node);
chain.push_back(new_node);
}
if(free_nodes.empty()){
m_block_multiset.erase(m_block_multiset.begin());
}
@@ -240,41 +243,23 @@ class private_adaptive_node_pool_impl
}
}
catch(...){
this->deallocate_nodes(nodes, nodes.size());
this->deallocate_nodes(chain, i);
throw;
}
priv_invariants();
}
//!Allocates n nodes, pointed by the multiallocation_iterator.
//!Can throw boost::interprocess::bad_alloc
multiallocation_iterator allocate_nodes(const std::size_t n)
{
multiallocation_chain chain;
this->allocate_nodes(chain, n);
return chain.get_it();
return boost::interprocess::move(chain);
}
//!Deallocates a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes)
void deallocate_nodes(multiallocation_chain nodes)
{
this->deallocate_nodes(nodes.get_it());
nodes.reset();
return deallocate_nodes(nodes, nodes.size());
}
//!Deallocates the first n nodes of a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes, std::size_t n)
{
assert(nodes.size() >= n);
for(std::size_t i = 0; i < n; ++i){
this->deallocate_node(nodes.pop_front());
}
}
//!Deallocates the nodes pointed by the multiallocation iterator. Never throws
void deallocate_nodes(multiallocation_iterator it)
{
this->priv_reinsert_nodes_in_block(it);
this->priv_reinsert_nodes_in_block(nodes, n);
if(m_totally_free_blocks > m_max_free_blocks){
this->priv_deallocate_free_blocks(m_max_free_blocks);
}
@@ -331,13 +316,12 @@ class private_adaptive_node_pool_impl
}
}
void priv_reinsert_nodes_in_block(multiallocation_iterator it)
void priv_reinsert_nodes_in_block(multiallocation_chain &chain, std::size_t n)
{
multiallocation_iterator itend;
block_iterator block_it(m_block_multiset.end());
while(it != itend){
void *pElem = &*it;
++it;
while(n--){
void *pElem = detail::get_pointer(chain.front());
chain.pop_front();
priv_invariants();
block_info_t *block_info = this->priv_block_from_node(pElem);
assert(block_info->free_nodes.size() < m_real_num_node);
@@ -484,6 +468,7 @@ class private_adaptive_node_pool_impl
std::size_t num_free_nodes = 0;
for(; it != itend; ++it){
//Check for memory leak
std::size_t n = (std::size_t)it->free_nodes.size(); (void)n;
assert(it->free_nodes.size() == m_real_num_node);
++num_free_nodes;
}
@@ -565,7 +550,7 @@ class private_adaptive_node_pool_impl
}
private:
typedef typename pointer_to_other
typedef typename boost::pointer_to_other
<void_pointer, segment_manager_base_type>::type segment_mngr_base_ptr_t;
const std::size_t m_max_free_blocks;

View File

@@ -8,25 +8,63 @@
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_NODE_ALLOCATOR_COMMON_HPP
#define BOOST_INTERPROCESS_DETAIL_NODE_ALLOCATOR_COMMON_HPP
#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
#define BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/segment_manager.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/detail/utilities.hpp> //pointer_to_other, get_pointer
#include <boost/interprocess/detail/utilities.hpp> //get_pointer
#include <utility> //std::pair
#include <boost/utility/addressof.hpp> //boost::addressof
#include <boost/assert.hpp> //BOOST_ASSERT
#include <boost/interprocess/exceptions.hpp> //bad_alloc
#include <boost/interprocess/sync/scoped_lock.hpp> //scoped_lock
#include <boost/interprocess/allocators/allocation_type.hpp> //allocation_type
#include <boost/interprocess/containers/allocation_type.hpp> //boost::interprocess::allocation_type
#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
#include <boost/interprocess/detail/segment_manager_helper.hpp>
#include <algorithm> //std::swap
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/utilities.hpp>
namespace boost {
namespace interprocess {
template <class T>
struct sizeof_value
{
static const std::size_t value = sizeof(T);
};
template <>
struct sizeof_value<void>
{
static const std::size_t value = sizeof(void*);
};
template <>
struct sizeof_value<const void>
{
static const std::size_t value = sizeof(void*);
};
template <>
struct sizeof_value<volatile void>
{
static const std::size_t value = sizeof(void*);
};
template <>
struct sizeof_value<const volatile void>
{
static const std::size_t value = sizeof(void*);
};
namespace detail {
//!Object function that creates the node allocator if it is not created and
@@ -41,7 +79,7 @@ struct get_or_create_node_pool_func
{
//Find or create the node_pool_t
mp_node_pool = mp_segment_manager->template find_or_construct
<NodePool>(unique_instance)(mp_segment_manager);
<NodePool>(boost::interprocess::unique_instance)(mp_segment_manager);
//If valid, increment link count
if(mp_node_pool != 0)
mp_node_pool->inc_ref_count();
@@ -78,7 +116,7 @@ struct destroy_if_last_link_func
if(mp_node_pool->dec_ref_count() != 0) return;
//Last link, let's destroy the segment_manager
mp_node_pool->get_segment_manager()->template destroy<NodePool>(unique_instance);
mp_node_pool->get_segment_manager()->template destroy<NodePool>(boost::interprocess::unique_instance);
}
//!Constructor. Initializes function
@@ -106,16 +144,15 @@ template<class NodePool>
class cache_impl
{
typedef typename NodePool::segment_manager::
void_pointer void_pointer;
void_pointer void_pointer;
typedef typename pointer_to_other
<void_pointer, NodePool>::type node_pool_ptr;
typedef typename NodePool::multiallocation_chain multiallocation_chain;
node_pool_ptr mp_node_pool;
multiallocation_chain m_cached_nodes;
std::size_t m_max_cached_nodes;
<void_pointer, NodePool>::type node_pool_ptr;
typedef typename NodePool::multiallocation_chain multiallocation_chain;
node_pool_ptr mp_node_pool;
multiallocation_chain m_cached_nodes;
std::size_t m_max_cached_nodes;
public:
typedef typename NodePool::multiallocation_iterator multiallocation_iterator;
typedef typename NodePool::segment_manager segment_manager;
cache_impl(segment_manager *segment_mngr, std::size_t max_cached_nodes)
@@ -149,31 +186,34 @@ 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()){
mp_node_pool->allocate_nodes(m_cached_nodes, m_max_cached_nodes/2);
m_cached_nodes = mp_node_pool->allocate_nodes(m_max_cached_nodes/2);
}
return m_cached_nodes.pop_front();
void *ret = detail::get_pointer(m_cached_nodes.front());
m_cached_nodes.pop_front();
return ret;
}
multiallocation_iterator cached_allocation(std::size_t n)
multiallocation_chain cached_allocation(std::size_t n)
{
multiallocation_chain chain;
std::size_t count = n;
std::size_t 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 = m_cached_nodes.pop_front();
void *ret = detail::get_pointer(m_cached_nodes.front());
m_cached_nodes.pop_front();
chain.push_back(ret);
++allocated;
}
if(chain.size() != n){
mp_node_pool->allocate_nodes(chain, n - chain.size());
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);
}
assert(chain.size() == n);
chain.splice_back(m_cached_nodes);
return multiallocation_iterator(chain.get_it());
return boost::interprocess::move(chain);
}
BOOST_CATCH(...){
this->cached_deallocation(multiallocation_iterator(chain.get_it()));
this->cached_deallocation(boost::interprocess::move(chain));
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -192,15 +232,9 @@ class cache_impl
m_cached_nodes.push_front(ptr);
}
void cached_deallocation(multiallocation_iterator it)
void cached_deallocation(multiallocation_chain chain)
{
multiallocation_iterator itend;
while(it != itend){
void *addr = &*it;
++it;
m_cached_nodes.push_front(addr);
}
m_cached_nodes.splice_after(m_cached_nodes.before_begin(), chain);
//Check if cache is full
if(m_cached_nodes.size() >= m_max_cached_nodes){
@@ -225,7 +259,7 @@ class cache_impl
void deallocate_all_cached_nodes()
{
if(m_cached_nodes.empty()) return;
mp_node_pool->deallocate_nodes(m_cached_nodes);
mp_node_pool->deallocate_nodes(boost::interprocess::move(m_cached_nodes));
}
private:
@@ -257,9 +291,9 @@ class array_allocation_impl
typedef typename SegmentManager::void_pointer void_pointer;
public:
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -268,12 +302,9 @@ class array_allocation_impl
<const value_type>::type const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
public:
//!Returns maximum the number of objects the previously allocated memory
@@ -285,7 +316,7 @@ class array_allocation_impl
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0)
@@ -300,19 +331,17 @@ 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_iterator allocate_many(size_type elem_size, std::size_t num_elements)
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements)
{
return multiallocation_iterator
(this->derived()->get_segment_manager()->allocate_many(sizeof(T)*elem_size, num_elements));
return this->derived()->get_segment_manager()->allocate_many(sizeof(T)*elem_size, num_elements);
}
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements)
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements)
{
return multiallocation_iterator
(this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T)));
return this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T));
}
//!Allocates many elements of size elem_size in a contiguous block
@@ -321,8 +350,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_iterator it)
{ return this->derived()->get_segment_manager()->deallocate_many(it.base()); }
void deallocate_many(multiallocation_chain chain)
{ return this->derived()->get_segment_manager()->deallocate_many(boost::interprocess::move(chain)); }
//!Returns the number of elements that could be
//!allocated. Never throws
@@ -369,13 +398,13 @@ class node_pool_allocation_impl
{ return static_cast<Derived*>(this); }
typedef typename SegmentManager::void_pointer void_pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const void>::type cvoid_pointer;
public:
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -384,12 +413,9 @@ class node_pool_allocation_impl
<const value_type>::type const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
template <int Dummy>
struct node_pool
@@ -445,11 +471,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_iterator allocate_individual(std::size_t num_elements)
multiallocation_chain allocate_individual(std::size_t num_elements)
{
typedef typename node_pool<0>::type node_pool_t;
node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
return multiallocation_iterator(pool->allocate_nodes(num_elements));
return multiallocation_chain(pool->allocate_nodes(num_elements));
}
//!Deallocates memory previously allocated with allocate_one().
@@ -468,8 +494,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().
void deallocate_individual(multiallocation_iterator it)
{ node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes(it.base()); }
void deallocate_individual(multiallocation_chain chain)
{
node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes
(chain.extract_multiallocation_chain());
}
//!Deallocates all free blocks of the pool
void deallocate_free_blocks()
@@ -497,11 +526,10 @@ class cached_allocator_impl
typedef NodePool node_pool_t;
typedef typename NodePool::segment_manager segment_manager;
typedef typename segment_manager::void_pointer void_pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const void>::type cvoid_pointer;
typedef typename base_t::pointer pointer;
typedef typename base_t::size_type size_type;
typedef typename base_t::multiallocation_iterator multiallocation_iterator;
typedef typename base_t::multiallocation_chain multiallocation_chain;
typedef typename base_t::value_type value_type;
@@ -587,8 +615,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_iterator allocate_individual(std::size_t num_elements)
{ return multiallocation_iterator(this->m_cache.cached_allocation(num_elements)); }
multiallocation_chain allocate_individual(std::size_t num_elements)
{ return multiallocation_chain(this->m_cache.cached_allocation(num_elements)); }
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -602,8 +630,12 @@ 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_iterator it)
{ m_cache.cached_deallocation(it.base()); }
void deallocate_individual(multiallocation_chain chain)
{
typename node_pool_t::multiallocation_chain mem
(chain.extract_multiallocation_chain());
m_cache.cached_deallocation(boost::interprocess::move(mem));
}
//!Deallocates all free blocks of the pool
void deallocate_free_blocks()
@@ -655,11 +687,10 @@ class shared_pool_impl
{
public:
//!Segment manager typedef
typedef typename private_node_allocator_t::segment_manager segment_manager;
typedef typename private_node_allocator_t::
multiallocation_iterator multiallocation_iterator;
segment_manager segment_manager;
typedef typename private_node_allocator_t::
multiallocation_chain multiallocation_chain;
multiallocation_chain multiallocation_chain;
private:
typedef typename segment_manager::mutex_family::mutex_type mutex_type;
@@ -691,7 +722,7 @@ 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, std::size_t n)
@@ -701,10 +732,10 @@ class shared_pool_impl
//-----------------------
return private_node_allocator_t::allocate_nodes(nodes, n);
}
//!Allocates n nodes, pointed by the multiallocation_iterator.
*/
//!Allocates n nodes.
//!Can throw boost::interprocess::bad_alloc
multiallocation_iterator allocate_nodes(const std::size_t n)
multiallocation_chain allocate_nodes(const std::size_t n)
{
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
@@ -721,22 +752,13 @@ class shared_pool_impl
private_node_allocator_t::deallocate_nodes(nodes, num);
}
//!Deallocates a linked list of nodes ending in null pointer. Never throws
void deallocate_nodes(multiallocation_chain &nodes)
{
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//-----------------------
private_node_allocator_t::deallocate_nodes(nodes);
}
//!Deallocates the nodes pointed by the multiallocation iterator. Never throws
void deallocate_nodes(multiallocation_iterator it)
void deallocate_nodes(multiallocation_chain chain)
{
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//-----------------------
private_node_allocator_t::deallocate_nodes(it);
private_node_allocator_t::deallocate_nodes(boost::interprocess::move(chain));
}
//!Deallocates all the free blocks of memory. Never throws
@@ -814,4 +836,4 @@ class shared_pool_impl
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_ALLOCATOR_COMMON_HPP
#endif //#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP

View File

@@ -18,14 +18,17 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/math/common_factor_ct.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/math/common_factor_ct.hpp>
#include <boost/interprocess/detail/math_functions.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/allocators/detail/node_tools.hpp>
#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
#include <cstddef>
#include <functional>
@@ -53,7 +56,6 @@ class private_node_pool_impl
typedef typename node_slist<void_pointer>::slist_hook_t slist_hook_t;
typedef typename node_slist<void_pointer>::node_t node_t;
typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
typedef typename SegmentManagerBase::multiallocation_iterator multiallocation_iterator;
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
private:
@@ -112,25 +114,9 @@ class private_node_pool_impl
--m_allocated;
}
//!Allocates a singly linked list of n nodes ending in null pointer and pushes them in the chain.
//!can throw boost::interprocess::bad_alloc
void allocate_nodes(multiallocation_chain &nodes, const std::size_t n)
{
std::size_t i = 0;
try{
for(; i < n; ++i){
nodes.push_front(this->allocate_node());
}
}
catch(...){
this->deallocate_nodes(nodes, i);
throw;
}
}
//!Allocates a singly linked list of n nodes ending in null pointer
//!can throw boost::interprocess::bad_alloc
multiallocation_iterator allocate_nodes(const std::size_t n)
multiallocation_chain allocate_nodes(const std::size_t n)
{
multiallocation_chain nodes;
std::size_t i = 0;
@@ -143,32 +129,26 @@ class private_node_pool_impl
this->deallocate_nodes(nodes, i);
throw;
}
return nodes.get_it();
}
//!Deallocates a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes)
{
this->deallocate_nodes(nodes.get_it());
nodes.reset();
return boost::interprocess::move(nodes);
}
//!Deallocates the first n nodes of a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes, std::size_t num)
void deallocate_nodes(multiallocation_chain &nodes, std::size_t n)
{
assert(nodes.size() >= num);
for(std::size_t i = 0; i < num; ++i){
deallocate_node(nodes.pop_front());
for(std::size_t i = 0; i < n; ++i){
void *p = detail::get_pointer(nodes.front());
assert(p);
nodes.pop_front();
this->deallocate_node(p);
}
}
//!Deallocates the nodes pointed by the multiallocation iterator. Never throws
void deallocate_nodes(multiallocation_iterator it)
void deallocate_nodes(multiallocation_chain chain)
{
multiallocation_iterator itend;
while(it != itend){
void *addr = &*it;
++it;
while(!chain.empty()){
void *addr = detail::get_pointer(chain.front());
chain.pop_front();
deallocate_node(addr);
}
}
@@ -347,7 +327,7 @@ class private_node_pool_impl
}
private:
typedef typename pointer_to_other
typedef typename boost::pointer_to_other
<void_pointer, segment_manager_base_type>::type segment_mngr_base_ptr_t;
const std::size_t m_nodes_per_block;

View File

@@ -18,6 +18,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
@@ -77,9 +79,9 @@ class node_allocator_base
public:
//-------
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -89,13 +91,9 @@ class node_allocator_base
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef detail::version_type<node_allocator_base, Version> version;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef boost::interprocess::version_type<node_allocator_base, Version> version;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
//!Obtains node_allocator_base from
//!node_allocator_base
@@ -251,7 +249,7 @@ class node_allocator
typedef detail::node_allocator_base
< 2, T, SegmentManager, NodesPerBlock> base_t;
public:
typedef detail::version_type<node_allocator, 2> version;
typedef boost::interprocess::version_type<node_allocator, 2> version;
template<class T2>
struct rebind
@@ -373,7 +371,7 @@ class node_allocator
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -384,12 +382,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_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -397,7 +395,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_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -410,7 +408,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_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -423,7 +421,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_iterator it);
void deallocate_individual(multiallocation_chain chain);
#endif
};

View File

@@ -18,6 +18,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
@@ -78,9 +80,9 @@ class private_adaptive_pool_base
/// @endcond
public:
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -89,14 +91,10 @@ class private_adaptive_pool_base
<const value_type>::type const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef detail::version_type
typedef boost::interprocess::version_type
<private_adaptive_pool_base, Version> version;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
//!Obtains node_allocator from other node_allocator
template<class T2>
@@ -264,7 +262,7 @@ class private_adaptive_pool
typedef detail::private_adaptive_pool_base
< 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
public:
typedef detail::version_type<private_adaptive_pool, 2> version;
typedef boost::interprocess::version_type<private_adaptive_pool, 2> version;
template<class T2>
struct rebind
@@ -388,7 +386,7 @@ class private_adaptive_pool
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -399,12 +397,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_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -412,7 +410,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_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -425,7 +423,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_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -438,7 +436,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_iterator it);
void deallocate_individual(multiallocation_chain chain);
#endif
};

View File

@@ -18,6 +18,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
@@ -72,9 +74,9 @@ class private_node_allocator_base
/// @endcond
public:
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -83,14 +85,10 @@ class private_node_allocator_base
<const value_type>::type const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef detail::version_type
typedef boost::interprocess::version_type
<private_node_allocator_base, Version> version;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
//!Obtains node_allocator from other node_allocator
template<class T2>
@@ -240,7 +238,7 @@ class private_node_allocator
typedef detail::private_node_allocator_base
< 2, T, SegmentManager, NodesPerBlock> base_t;
public:
typedef detail::version_type<private_node_allocator, 2> version;
typedef boost::interprocess::version_type<private_node_allocator, 2> version;
template<class T2>
struct rebind
@@ -364,7 +362,7 @@ class private_node_allocator
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -375,12 +373,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_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -388,7 +386,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_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -401,7 +399,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_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -414,7 +412,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_iterator it);
void deallocate_individual(multiallocation_chain chain);
#endif
};

View File

@@ -19,7 +19,7 @@
#include <boost/interprocess/mapped_region.hpp>
#include <cstddef>
#if (!defined(BOOST_WINDOWS)) || defined(BOOST_DISABLE_WIN32)
#if (!defined(BOOST_INTERPROCESS_WINDOWS))
# include <fcntl.h> //open, O_CREAT, O_*...
# include <sys/mman.h> //mmap
# include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
@@ -42,12 +42,7 @@ namespace detail{
class raw_mapped_region_creator
{
public:
static
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
mapped_region
#else
move_return<mapped_region>
#endif
static mapped_region
create_posix_mapped_region(void *address, offset_t offset, std::size_t size)
{
mapped_region region;
@@ -67,14 +62,10 @@ namespace detail{
//!Otherwise the operating system will choose the mapping address.
//!The function returns a mapped_region holding that segment or throws
//!interprocess_exception if the function fails.
static
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
mapped_region
#else
detail::move_return<mapped_region>
#endif
//static mapped_region
static mapped_region
anonymous_shared_memory(std::size_t size, void *address = 0)
#if (!defined(BOOST_WINDOWS)) || defined(BOOST_DISABLE_WIN32)
#if (!defined(BOOST_INTERPROCESS_WINDOWS))
{
int flags;
int fd = -1;
@@ -115,8 +106,7 @@ anonymous_shared_memory(std::size_t size, void *address = 0)
#else
{
windows_shared_memory anonymous_mapping(create_only, 0, read_write, size);
mapped_region region(anonymous_mapping, read_write, 0, size, address);
return region;
return mapped_region(anonymous_mapping, read_write, 0, size, address);
}
#endif

View File

@@ -0,0 +1,40 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2009. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP
#define BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/allocation_type.hpp>
namespace boost {
namespace interprocess {
/// @cond
typedef int allocation_type;
/// @endcond
static const allocation_type allocate_new = boost::interprocess_container::allocate_new;
static const allocation_type expand_fwd = boost::interprocess_container::expand_fwd;
static const allocation_type expand_bwd = boost::interprocess_container::expand_bwd;
static const allocation_type shrink_in_place = boost::interprocess_container::shrink_in_place;
static const allocation_type try_shrink_in_place= boost::interprocess_container::try_shrink_in_place;
static const allocation_type nothrow_allocation = boost::interprocess_container::nothrow_allocation;
static const allocation_type zero_memory = boost::interprocess_container::zero_memory;
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP

View File

@@ -0,0 +1,153 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_CONTAINERS_FWD_HPP
#define BOOST_CONTAINERS_CONTAINERS_FWD_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
//////////////////////////////////////////////////////////////////////////////
// Standard predeclarations
//////////////////////////////////////////////////////////////////////////////
/// @cond
namespace boost{
namespace intrusive{
//Create namespace to avoid compilation errors
}}
namespace boost{ namespace interprocess_container{ namespace containers_detail{
namespace bi = boost::intrusive;
}}}
namespace std {
template <class T>
class allocator;
template <class T>
struct less;
template <class T1, class T2>
struct pair;
template <class CharType>
struct char_traits;
} //namespace std {
/// @endcond
//////////////////////////////////////////////////////////////////////////////
// Containers
//////////////////////////////////////////////////////////////////////////////
#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
namespace boost {
namespace interprocess {
#else
namespace boost {
namespace interprocess_container {
#endif
//vector class
template <class T
,class A = std::allocator<T> >
class vector;
//vector class
template <class T
,class A = std::allocator<T> >
class deque;
//list class
template <class T
,class A = std::allocator<T> >
class list;
//slist class
template <class T
,class Alloc = std::allocator<T> >
class slist;
//set class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class set;
//multiset class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class multiset;
//map class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<const Key, T> > >
class map;
//multimap class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<const Key, T> > >
class multimap;
//flat_set class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class flat_set;
//flat_multiset class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class flat_multiset;
//flat_map class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<Key, T> > >
class flat_map;
//flat_multimap class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<Key, T> > >
class flat_multimap;
//basic_string class
template <class CharT
,class Traits = std::char_traits<CharT>
,class Alloc = std::allocator<CharT> >
class basic_string;
//string class
typedef basic_string
<char
,std::char_traits<char>
,std::allocator<char> >
string;
}} //namespace boost { namespace interprocess_container {
#endif //#ifndef BOOST_CONTAINERS_CONTAINERS_FWD_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -4,26 +4,26 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP
#define BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP
#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
#define BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <iterator> //std::iterator_traits
#include <algorithm> //std::copy, std::uninitialized_copy
#include <new> //placement new
#include <cassert>
namespace boost { namespace interprocess { namespace detail {
namespace boost { namespace interprocess_container { namespace containers_detail {
//This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl
template<class T, class Iterator>
@@ -51,21 +51,21 @@ struct advanced_insert_aux_proxy
{}
virtual void copy_all_to(Iterator p)
{ *std::copy(first_, last_, p); }
{ std::copy(first_, last_, p); }
virtual void uninitialized_copy_all_to(Iterator p)
{ std::uninitialized_copy(first_, last_, p); }
{ boost::interprocess::uninitialized_copy_or_move(first_, last_, p); }
virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
{
FwdIt mid = first_;
std::advance(mid, division_count);
if(first_n){
std::uninitialized_copy(first_, mid, pos);
boost::interprocess::uninitialized_copy_or_move(first_, mid, pos);
first_ = mid;
}
else{
std::uninitialized_copy(mid, last_, pos);
boost::interprocess::uninitialized_copy_or_move(mid, last_, pos);
last_ = mid;
}
}
@@ -104,12 +104,12 @@ struct default_construct_aux_proxy
SizeType i = 0;
try{
for(; i < n; ++i, ++p){
new(detail::get_pointer(&*p))T();
new(containers_detail::get_pointer(&*p))T();
}
}
catch(...){
while(i--){
detail::get_pointer(&*orig_p++)->~T();
containers_detail::get_pointer(&*orig_p++)->~T();
}
throw;
}
@@ -159,18 +159,18 @@ struct default_construct_aux_proxy
SizeType count_;
};
}}} //namespace boost { namespace interprocess { namespace detail {
}}} //namespace boost { namespace interprocess_container { namespace containers_detail {
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/detail/variadic_templates_tools.hpp>
#include <boost/interprocess/containers/container/detail/variadic_templates_tools.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <typeinfo>
//#include <iostream> //For debugging purposes
namespace boost {
namespace interprocess {
namespace detail {
namespace interprocess_container {
namespace containers_detail {
//This class template will adapt each FwIt types to advanced_insert_aux_int
template<class T, class Iterator, class ...Args>
@@ -204,8 +204,8 @@ struct advanced_insert_aux_emplace
void priv_copy_all_to(const index_tuple<IdxPack...>&, Iterator p)
{
if(!used_){
T object(detail::forward_impl<Args>(get<IdxPack>(args_))...);
*p = detail::move_impl(object);
T object(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
*p = boost::interprocess::move(object);
used_ = true;
}
}
@@ -214,7 +214,7 @@ struct advanced_insert_aux_emplace
void priv_uninitialized_copy_all_to(const index_tuple<IdxPack...>&, Iterator p)
{
if(!used_){
new(detail::get_pointer(&*p))T(detail::forward_impl<Args>(get<IdxPack>(args_))...);
new(containers_detail::get_pointer(&*p))T(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
used_ = true;
}
}
@@ -225,7 +225,7 @@ struct advanced_insert_aux_emplace
assert(division_count <=1);
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
if(!used_){
new(detail::get_pointer(&*p))T(detail::forward_impl<Args>(get<IdxPack>(args_))...);
new(containers_detail::get_pointer(&*p))T(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
used_ = true;
}
}
@@ -237,8 +237,8 @@ struct advanced_insert_aux_emplace
assert(division_count <=1);
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
if(!used_){
T object(detail::forward_impl<Args>(get<IdxPack>(args_))...);
*p = detail::move_impl(object);
T object(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
*p = boost::interprocess::move(object);
used_ = true;
}
}
@@ -247,25 +247,16 @@ struct advanced_insert_aux_emplace
bool used_;
};
}}} //namespace boost { namespace interprocess { namespace detail {
}}} //namespace boost { namespace interprocess_container { namespace containers_detail {
#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/detail/preprocessor.hpp>
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
#include <boost/interprocess/containers/container/detail/value_init.hpp>
namespace boost {
namespace interprocess {
namespace detail {
template<class T>
struct value_init_helper
{
value_init_helper()
: m_t()
{}
T m_t;
};
namespace interprocess_container {
namespace containers_detail {
//This class template will adapt each FwIt types to advanced_insert_aux_int
template<class T, class Iterator>
@@ -283,8 +274,8 @@ struct advanced_insert_aux_emplace
virtual void copy_all_to(Iterator p)
{
if(!used_){
value_init_helper<T>v;
*p = detail::move_impl(v.m_t);
value_init<T>v;
*p = boost::interprocess::move(v.m_t);
used_ = true;
}
}
@@ -292,7 +283,7 @@ struct advanced_insert_aux_emplace
virtual void uninitialized_copy_all_to(Iterator p)
{
if(!used_){
new(detail::get_pointer(&*p))T();
new(containers_detail::get_pointer(&*p))T();
used_ = true;
}
}
@@ -302,7 +293,7 @@ struct advanced_insert_aux_emplace
assert(division_count <=1);
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
if(!used_){
new(detail::get_pointer(&*p))T();
new(containers_detail::get_pointer(&*p))T();
used_ = true;
}
}
@@ -313,8 +304,8 @@ struct advanced_insert_aux_emplace
assert(division_count <=1);
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
if(!used_){
value_init_helper<T>v;
*p = detail::move_impl(v.m_t);
value_init<T>v;
*p = boost::interprocess::move(v.m_t);
used_ = true;
}
}
@@ -331,14 +322,14 @@ struct advanced_insert_aux_emplace
typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; \
\
BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \
: used_(false), BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INIT, _) {} \
( BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _) ) \
: used_(false), BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {} \
\
virtual void copy_all_to(Iterator p) \
{ \
if(!used_){ \
T v(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
*p = detail::move_impl(v); \
T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
*p = boost::interprocess::move(v); \
used_ = true; \
} \
} \
@@ -346,8 +337,8 @@ struct advanced_insert_aux_emplace
virtual void uninitialized_copy_all_to(Iterator p) \
{ \
if(!used_){ \
new(detail::get_pointer(&*p))T \
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
new(containers_detail::get_pointer(&*p))T \
(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
used_ = true; \
} \
} \
@@ -358,8 +349,8 @@ struct advanced_insert_aux_emplace
assert(division_count <=1); \
if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
if(!used_){ \
new(detail::get_pointer(&*p))T \
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
new(containers_detail::get_pointer(&*p))T \
(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
used_ = true; \
} \
} \
@@ -371,25 +362,25 @@ struct advanced_insert_aux_emplace
assert(division_count <=1); \
if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
if(!used_){ \
T v(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
*p = detail::move_impl(v); \
T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
*p = boost::interprocess::move(v); \
used_ = true; \
} \
} \
} \
\
bool used_; \
BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_AUX_PARAM_DEFINE, _) \
BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _) \
}; \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
}}} //namespace boost { namespace interprocess { namespace detail {
}}} //namespace boost { namespace interprocess_container { namespace containers_detail {
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP
#endif //#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP

View File

@@ -6,71 +6,81 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_ALGORITHMS_HPP
#define BOOST_INTERPROCESS_DETAIL_ALGORITHMS_HPP
#ifndef BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP
#define BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/iterators.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_assign.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/get_pointer.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <boost/interprocess/containers/container/detail/mpl.hpp>
#include <boost/interprocess/containers/container/detail/iterators.hpp>
#include <cstring>
namespace boost {
namespace interprocess {
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) || !defined(BOOST_INTERPROCESS_RVALUE_PAIR)
namespace interprocess_container {
#if !defined(BOOST_HAS_RVALUE_REFS)
template<class T>
struct has_own_construct_from_it
{
static const bool value = false;
};
namespace detail {
namespace containers_detail {
template<class T, class InpIt>
inline void construct_in_place_impl(T* dest, const InpIt &source, detail::true_)
inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::true_)
{
T::construct(dest, *source);
}
template<class T, class InpIt>
inline void construct_in_place_impl(T* dest, const InpIt &source, detail::false_)
inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::false_)
{
new((void*)dest)T(*source);
}
} //namespace detail {
} //namespace containers_detail {
template<class T, class InpIt>
inline void construct_in_place(T* dest, InpIt source)
{
typedef detail::bool_<has_own_construct_from_it<T>::value> boolean_t;
detail::construct_in_place_impl(dest, source, boolean_t());
typedef containers_detail::bool_<has_own_construct_from_it<T>::value> boolean_t;
containers_detail::construct_in_place_impl(dest, source, boolean_t());
}
#else
template<class T, class InpIt>
inline void construct_in_place(T* dest, InpIt source)
{ new((void*)dest)T(*source); }
{ ::new((void*)dest)T(*source); }
#endif
template<class T, class U, class D>
inline void construct_in_place(T *dest, default_construct_iterator<U, D>)
{
new((void*)dest)T();
::new((void*)dest)T();
}
template<class T, class U, class E>
inline void construct_in_place(T *dest, emplace_iterator<U, E> ei)
{
ei.construct_in_place(dest);
}
template<class InIt, class OutIt>
@@ -108,7 +118,7 @@ struct optimize_copy<T*, T*>
{};
template<class InIt, class OutIt> inline
OutIt copy_n_dispatch(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest, detail::bool_<false>)
OutIt copy_n_dispatch(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest, containers_detail::bool_<false>)
{
for (; length--; ++dest, ++first)
*dest = *first;
@@ -116,7 +126,7 @@ OutIt copy_n_dispatch(InIt first, typename std::iterator_traits<InIt>::differenc
}
template<class T> inline
T *copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, detail::bool_<true>)
T *copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, containers_detail::bool_<true>)
{
std::size_t size = length*sizeof(T);
return (static_cast<T*>(std::memmove(dest, first, size))) + size;
@@ -126,14 +136,14 @@ template<class InIt, class OutIt> inline
OutIt copy_n(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest)
{
const bool do_optimized_assign = optimize_assign<InIt, OutIt>::value;
return copy_n_dispatch(first, length, dest, detail::bool_<do_optimized_assign>());
return copy_n_dispatch(first, length, dest, containers_detail::bool_<do_optimized_assign>());
}
template<class InIt, class FwdIt> inline
FwdIt uninitialized_copy_n_dispatch
(InIt first,
typename std::iterator_traits<InIt>::difference_type count,
FwdIt dest, detail::bool_<false>)
FwdIt dest, containers_detail::bool_<false>)
{
typedef typename std::iterator_traits<FwdIt>::value_type value_type;
//Save initial destination position
@@ -143,14 +153,14 @@ FwdIt uninitialized_copy_n_dispatch
BOOST_TRY{
//Try to build objects
for (; --new_count; ++dest, ++first){
construct_in_place(detail::get_pointer(&*dest), first);
construct_in_place(containers_detail::get_pointer(&*dest), first);
}
}
BOOST_CATCH(...){
//Call destructors
new_count = count - new_count;
for (; new_count--; ++dest_init){
detail::get_pointer(&*dest_init)->~value_type();
containers_detail::get_pointer(&*dest_init)->~value_type();
}
BOOST_RETHROW
}
@@ -158,7 +168,7 @@ FwdIt uninitialized_copy_n_dispatch
return dest;
}
template<class T> inline
T *uninitialized_copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, detail::bool_<true>)
T *uninitialized_copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, containers_detail::bool_<true>)
{
std::size_t size = length*sizeof(T);
return (static_cast<T*>(std::memmove(dest, first, size))) + size;
@@ -171,7 +181,7 @@ FwdIt uninitialized_copy_n
FwdIt dest)
{
const bool do_optimized_copy = optimize_copy<InIt, FwdIt>::value;
return uninitialized_copy_n_dispatch(first, count, dest, detail::bool_<do_optimized_copy>());
return uninitialized_copy_n_dispatch(first, count, dest, containers_detail::bool_<do_optimized_copy>());
}
// uninitialized_copy_copy
@@ -189,17 +199,17 @@ FwdIt uninitialized_copy_copy
}
BOOST_CATCH(...){
for(;result != mid; ++result){
detail::get_pointer(&*result)->~value_type();
containers_detail::get_pointer(&*result)->~value_type();
}
BOOST_RETHROW
}
BOOST_CATCH_END
}
} //namespace interprocess {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ALGORITHMS_HPP
#endif //#ifndef BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP

View File

@@ -4,22 +4,22 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
// See http://www.boost.org/libs/container for documentation.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_TYPE_COMMAND_HPP
#define BOOST_INTERPROCESS_TYPE_COMMAND_HPP
#ifndef BOOST_CONTAINERS_ALLOCATION_TYPE_HPP
#define BOOST_CONTAINERS_ALLOCATION_TYPE_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
namespace boost {
namespace interprocess {
namespace interprocess_container {
/// @cond
enum allocation_type_v
@@ -46,10 +46,9 @@ static const allocation_type try_shrink_in_place= (allocation_type)try_shrink_in
static const allocation_type nothrow_allocation = (allocation_type)nothrow_allocation_v;
static const allocation_type zero_memory = (allocation_type)zero_memory_v;
} //namespace interprocess {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_TYPE_COMMAND_HPP
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //BOOST_CONTAINERS_ALLOCATION_TYPE_HPP

View File

@@ -0,0 +1,47 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED
#define BOOST_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED
#include <boost/config.hpp>
#endif
#ifdef BOOST_MSVC
#ifndef _CRT_SECURE_NO_DEPRECATE
#define BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#pragma warning (push)
#pragma warning (disable : 4702) // unreachable code
#pragma warning (disable : 4706) // assignment within conditional expression
#pragma warning (disable : 4127) // conditional expression is constant
#pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
#pragma warning (disable : 4284) // odd return type for operator->
#pragma warning (disable : 4244) // possible loss of data
#pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2"
#pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data
#pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier"
#pragma warning (disable : 4355) // "this" : used in base member initializer list
#pragma warning (disable : 4503) // "identifier" : decorated name length exceeded, name was truncated
#pragma warning (disable : 4511) // copy constructor could not be generated
#pragma warning (disable : 4512) // assignment operator could not be generated
#pragma warning (disable : 4514) // unreferenced inline removed
#pragma warning (disable : 4521) // Disable "multiple copy constructors specified"
#pragma warning (disable : 4522) // "class" : multiple assignment operators specified
#pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter
#pragma warning (disable : 4710) // function not inlined
#pragma warning (disable : 4711) // function selected for automatic inline expansion
#pragma warning (disable : 4786) // identifier truncated in debug info
#pragma warning (disable : 4996) // "function": was declared deprecated
#pragma warning (disable : 4197) // top-level volatile in cast is ignored
#pragma warning (disable : 4541) // 'typeid' used on polymorphic type 'boost::exception'
// with /GR-; unpredictable behavior may result
#pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site
#pragma warning (disable : 4671) // the copy constructor is inaccessible
#endif

View File

@@ -0,0 +1,17 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#if defined BOOST_MSVC
#pragma warning (pop)
#ifdef BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE
#undef BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE
#undef _CRT_SECURE_NO_DEPRECATE
#endif
#endif

View File

@@ -0,0 +1,154 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2009.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DESTROYERS_HPP
#define BOOST_CONTAINERS_DESTROYERS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/version_type.hpp>
#include <boost/interprocess/containers/container/detail/utilities.hpp>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an array of objects using a STL allocator.
template <class Allocator>
struct scoped_array_deallocator
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::size_type size_type;
scoped_array_deallocator(pointer p, Allocator& a, size_type length)
: m_ptr(p), m_alloc(a), m_length(length) {}
~scoped_array_deallocator()
{ if (m_ptr) m_alloc.deallocate(m_ptr, m_length); }
void release()
{ m_ptr = 0; }
private:
pointer m_ptr;
Allocator& m_alloc;
size_type m_length;
};
template <class Allocator>
struct null_scoped_array_deallocator
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::size_type size_type;
null_scoped_array_deallocator(pointer, Allocator&, size_type)
{}
void release()
{}
};
//!A deleter for scoped_ptr that destroys
//!an object using a STL allocator.
template <class Allocator>
struct scoped_destructor_n
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::value_type value_type;
typedef typename Allocator::size_type size_type;
pointer m_p;
size_type m_n;
scoped_destructor_n(pointer p, size_type n)
: m_p(p), m_n(n)
{}
void release()
{ m_p = 0; }
void increment_size(size_type inc)
{ m_n += inc; }
~scoped_destructor_n()
{
if(!m_p) return;
value_type *raw_ptr = containers_detail::get_pointer(m_p);
for(std::size_t i = 0; i < m_n; ++i, ++raw_ptr)
raw_ptr->~value_type();
}
};
//!A deleter for scoped_ptr that destroys
//!an object using a STL allocator.
template <class Allocator>
struct null_scoped_destructor_n
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::size_type size_type;
null_scoped_destructor_n(pointer, size_type)
{}
void increment_size(size_type)
{}
void release()
{}
};
template <class A>
class allocator_destroyer
{
typedef typename A::value_type value_type;
typedef containers_detail::integral_constant<unsigned,
boost::interprocess_container::containers_detail::
version<A>::value> alloc_version;
typedef containers_detail::integral_constant<unsigned, 1> allocator_v1;
typedef containers_detail::integral_constant<unsigned, 2> allocator_v2;
private:
A & a_;
private:
void priv_deallocate(const typename A::pointer &p, allocator_v1)
{ a_.deallocate(p, 1); }
void priv_deallocate(const typename A::pointer &p, allocator_v2)
{ a_.deallocate_one(p); }
public:
allocator_destroyer(A &a)
: a_(a)
{}
void operator()(const typename A::pointer &p)
{
containers_detail::get_pointer(p)->~value_type();
priv_deallocate(p, alloc_version());
}
};
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DESTROYERS_HPP

View File

@@ -4,7 +4,7 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
// See http://www.boost.org/libs/container for documentation.
//
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
@@ -25,35 +25,40 @@
//
////////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_FLAT_TREE_HPP
#define BOOST_INTERPROCESS_FLAT_TREE_HPP
#ifndef BOOST_CONTAINERS_FLAT_TREE_HPP
#define BOOST_CONTAINERS_FLAT_TREE_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <algorithm>
#include <functional>
#include <utility>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/containers/container/detail/utilities.hpp>
#include <boost/interprocess/containers/container/detail/pair.hpp>
#include <boost/interprocess/containers/container/vector.hpp>
#include <boost/interprocess/containers/container/detail/value_init.hpp>
#include <boost/interprocess/containers/container/detail/destroyers.hpp>
namespace boost {
namespace interprocess {
namespace interprocess_container {
namespace detail {
namespace containers_detail {
template <class Key, class Value, class KeyOfValue,
class Compare, class Alloc>
class flat_tree
{
typedef boost::interprocess::vector<Value, Alloc> vector_t;
typedef boost::interprocess_container::vector<Value, Alloc> vector_t;
typedef Alloc allocator_t;
public:
@@ -105,6 +110,7 @@ class flat_tree
Data m_data;
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(flat_tree)
typedef typename vector_t::value_type value_type;
typedef typename vector_t::pointer pointer;
@@ -133,15 +139,9 @@ class flat_tree
: m_data(x.m_data, x.m_data.m_vect)
{ }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_tree(detail::moved_object<flat_tree> x)
: m_data(detail::move_impl(x.get().m_data))
flat_tree(BOOST_INTERPROCESS_RV_REF(flat_tree) x)
: m_data(boost::interprocess::move(x.m_data))
{ }
#else
flat_tree(flat_tree &&x)
: m_data(detail::move_impl(x.m_data))
{ }
#endif
~flat_tree()
{ }
@@ -149,13 +149,8 @@ class flat_tree
flat_tree& operator=(const flat_tree& x)
{ m_data = x.m_data; return *this; }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_tree& operator=(detail::moved_object<flat_tree> mx)
{ m_data = detail::move_impl(mx.get().m_data); return *this; }
#else
flat_tree& operator=(flat_tree &&mx)
{ m_data = detail::move_impl(mx.m_data); return *this; }
#endif
flat_tree& operator=(BOOST_INTERPROCESS_RV_REF(flat_tree) mx)
{ m_data = boost::interprocess::move(mx.m_data); return *this; }
public:
// accessors:
@@ -220,20 +215,12 @@ class flat_tree
{
value_compare& mycomp = this->m_data;
value_compare& othercomp = other.m_data;
detail::do_swap(mycomp, othercomp);
containers_detail::do_swap(mycomp, othercomp);
vector_t & myvect = this->m_data.m_vect;
vector_t & othervect = other.m_data.m_vect;
myvect.swap(othervect);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(detail::moved_object<flat_tree> other)
{ this->swap(other.get()); }
#else
void swap(flat_tree &&other)
{ this->swap(other); }
#endif
public:
// insert/erase
std::pair<iterator,bool> insert_unique(const value_type& val)
@@ -246,18 +233,12 @@ class flat_tree
return ret;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
std::pair<iterator,bool> insert_unique(detail::moved_object<value_type> mval)
std::pair<iterator,bool> insert_unique(BOOST_INTERPROCESS_RV_REF(value_type) val)
{
value_type &val = mval.get();
#else
std::pair<iterator,bool> insert_unique(value_type && val)
{
#endif
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl(val));
ret.first = priv_insert_commit(data, boost::interprocess::move(val));
}
return ret;
}
@@ -270,21 +251,12 @@ class flat_tree
return i;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert_equal(detail::moved_object<value_type> mval)
{
iterator i = this->upper_bound(KeyOfValue()(mval.get()));
i = this->m_data.m_vect.insert(i, mval);
return i;
}
#else
iterator insert_equal(value_type && mval)
iterator insert_equal(BOOST_INTERPROCESS_RV_REF(value_type) mval)
{
iterator i = this->upper_bound(KeyOfValue()(mval));
i = this->m_data.m_vect.insert(i, detail::move_impl(mval));
i = this->m_data.m_vect.insert(i, boost::interprocess::move(mval));
return i;
}
#endif
iterator insert_unique(const_iterator pos, const value_type& val)
{
@@ -296,27 +268,15 @@ class flat_tree
return ret.first;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert_unique(const_iterator pos, detail::moved_object<value_type> mval)
{
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, mval.get(), data);
if(ret.second){
ret.first = priv_insert_commit(data, mval);
}
return ret.first;
}
#else
iterator insert_unique(const_iterator pos, value_type&&mval)
iterator insert_unique(const_iterator pos, BOOST_INTERPROCESS_RV_REF(value_type) mval)
{
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, mval, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl(mval));
ret.first = priv_insert_commit(data, boost::interprocess::move(mval));
}
return ret.first;
}
#endif
iterator insert_equal(const_iterator pos, const value_type& val)
{
@@ -325,21 +285,12 @@ class flat_tree
return priv_insert_commit(data, val);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert_equal(const_iterator pos, detail::moved_object<value_type> mval)
{
insert_commit_data data;
priv_insert_equal_prepare(pos, mval.get(), data);
return priv_insert_commit(data, mval);
}
#else
iterator insert_equal(const_iterator pos, value_type && mval)
iterator insert_equal(const_iterator pos, BOOST_INTERPROCESS_RV_REF(value_type) mval)
{
insert_commit_data data;
priv_insert_equal_prepare(pos, mval, data);
return priv_insert_commit(data, detail::move_impl(mval));
return priv_insert_commit(data, boost::interprocess::move(mval));
}
#endif
template <class InIt>
void insert_unique(InIt first, InIt last)
@@ -356,17 +307,17 @@ class flat_tree
priv_insert_equal(first, last, ItCat());
}
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
template <class... Args>
iterator emplace_unique(Args&&... args)
{
value_type val(detail::forward_impl<Args>(args)...);
value_type val(boost::interprocess::forward<Args>(args)...);
insert_commit_data data;
std::pair<iterator,bool> ret =
priv_insert_unique_prepare(val, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
return ret.first;
}
@@ -374,11 +325,11 @@ class flat_tree
template <class... Args>
iterator emplace_hint_unique(const_iterator hint, Args&&... args)
{
value_type val(detail::forward_impl<Args>(args)...);
value_type val(boost::interprocess::forward<Args>(args)...);
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
return ret.first;
}
@@ -386,115 +337,115 @@ class flat_tree
template <class... Args>
iterator emplace_equal(Args&&... args)
{
value_type val(detail::forward_impl<Args>(args)...);
value_type val(boost::interprocess::forward<Args>(args)...);
iterator i = this->upper_bound(KeyOfValue()(val));
i = this->m_data.m_vect.insert(i, detail::move_impl<value_type>(val));
i = this->m_data.m_vect.insert(i, boost::interprocess::move<value_type>(val));
return i;
}
template <class... Args>
iterator emplace_hint_equal(const_iterator hint, Args&&... args)
{
value_type val(detail::forward_impl<Args>(args)...);
value_type val(boost::interprocess::forward<Args>(args)...);
insert_commit_data data;
priv_insert_equal_prepare(hint, val, data);
return priv_insert_commit(data, detail::move_impl<value_type>(val));
return priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
iterator emplace_unique()
{
detail::value_init<value_type> vval;
containers_detail::value_init<value_type> vval;
value_type &val = vval.m_t;
insert_commit_data data;
std::pair<iterator,bool> ret =
priv_insert_unique_prepare(val, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
return ret.first;
}
iterator emplace_hint_unique(const_iterator hint)
{
detail::value_init<value_type> vval;
containers_detail::value_init<value_type> vval;
value_type &val = vval.m_t;
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
return ret.first;
}
iterator emplace_equal()
{
detail::value_init<value_type> vval;
containers_detail::value_init<value_type> vval;
value_type &val = vval.m_t;
iterator i = this->upper_bound(KeyOfValue()(val));
i = this->m_data.m_vect.insert(i, detail::move_impl<value_type>(val));
i = this->m_data.m_vect.insert(i, boost::interprocess::move<value_type>(val));
return i;
}
iterator emplace_hint_equal(const_iterator hint)
{
detail::value_init<value_type> vval;
containers_detail::value_init<value_type> vval;
value_type &val = vval.m_t;
insert_commit_data data;
priv_insert_equal_prepare(hint, val, data);
return priv_insert_commit(data, detail::move_impl<value_type>(val));
return priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
insert_commit_data data; \
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data); \
if(ret.second){ \
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val)); \
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val)); \
} \
return ret.first; \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_hint_unique(const_iterator hint, \
BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
insert_commit_data data; \
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data); \
if(ret.second){ \
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val)); \
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val)); \
} \
return ret.first; \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
iterator i = this->upper_bound(KeyOfValue()(val)); \
i = this->m_data.m_vect.insert(i, detail::move_impl<value_type>(val)); \
i = this->m_data.m_vect.insert(i, boost::interprocess::move<value_type>(val)); \
return i; \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_hint_equal(const_iterator hint, \
BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
insert_commit_data data; \
priv_insert_equal_prepare(hint, val, data); \
return priv_insert_commit(data, detail::move_impl<value_type>(val)); \
return priv_insert_commit(data, boost::interprocess::move<value_type>(val)); \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
iterator erase(const_iterator position)
{ return this->m_data.m_vect.erase(position); }
@@ -682,17 +633,14 @@ class flat_tree
}
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
iterator priv_insert_commit
(insert_commit_data &commit_data, const Convertible &convertible)
{ return this->m_data.m_vect.insert(commit_data.position, convertible); }
#else
template<class Convertible>
iterator priv_insert_commit
(insert_commit_data &commit_data, Convertible &&convertible)
{ return this->m_data.m_vect.insert(commit_data.position, detail::forward_impl<Convertible>(convertible)); }
#endif
(insert_commit_data &commit_data, BOOST_INTERPROCESS_FWD_REF(Convertible) convertible)
{
return this->m_data.m_vect.insert
( commit_data.position
, boost::interprocess::forward<Convertible>(convertible));
}
template <class RanIt>
RanIt priv_lower_bound(RanIt first, RanIt last,
@@ -865,23 +813,25 @@ swap(flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
{ x.swap(y); }
} //namespace detail {
} //namespace containers_detail {
} //namespace interprocess_container {
namespace interprocess {
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class K, class V, class KOV,
class C, class A>
struct has_trivial_destructor_after_move<detail::flat_tree<K, V, KOV, C, A> >
class C, class A>
struct has_trivial_destructor_after_move<boost::interprocess_container::containers_detail::flat_tree<K, V, KOV, C, A> >
{
enum { value =
has_trivial_destructor<A>::value &&
has_trivial_destructor<C>::value };
static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
};
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif // BOOST_INTERPROCESS_FLAT_TREE_HPP
#endif // BOOST_CONTAINERS_FLAT_TREE_HPP

View File

@@ -7,27 +7,31 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_ITERATORS_HPP
#define BOOST_INTERPROCESS_DETAIL_ITERATORS_HPP
#ifndef BOOST_CONTAINERS_DETAIL_ITERATORS_HPP
#define BOOST_CONTAINERS_DETAIL_ITERATORS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/containers/container/detail/variadic_templates_tools.hpp>
#else
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
#endif
#include <iterator>
#include <boost/interprocess/detail/type_traits.hpp>
namespace boost {
namespace interprocess {
namespace interprocess_container {
template <class T, class Difference = std::ptrdiff_t>
class constant_iterator
@@ -324,152 +328,165 @@ class repeat_iterator
{ return m_num - other.m_num; }
};
template <class PseudoReference>
struct operator_arrow_proxy
template <class T, class E>
class emplace_iterator
: public std::iterator
<std::random_access_iterator_tag, T, std::ptrdiff_t, const T*, const T &>
{
operator_arrow_proxy(const PseudoReference &px)
: m_value(px)
{}
typedef emplace_iterator this_type;
PseudoReference* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
mutable PseudoReference m_value;
};
template <class T>
struct operator_arrow_proxy<T&>
{
operator_arrow_proxy(T &px)
: m_value(px)
{}
T* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
mutable T &m_value;
};
template <class Iterator, class UnaryFunction>
class transform_iterator
: public UnaryFunction
, public std::iterator
< typename Iterator::iterator_category
, typename detail::remove_reference<typename UnaryFunction::result_type>::type
, typename Iterator::difference_type
, operator_arrow_proxy<typename UnaryFunction::result_type>
, typename UnaryFunction::result_type>
{
public:
explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
: UnaryFunction(f), m_it(it)
{}
explicit emplace_iterator(E&e)
: m_num(1), m_pe(&e){}
explicit transform_iterator()
: UnaryFunction(), m_it()
{}
emplace_iterator()
: m_num(0), m_pe(0){}
//Constructors
transform_iterator& operator++()
this_type& operator++()
{ increment(); return *this; }
transform_iterator operator++(int)
this_type operator++(int)
{
transform_iterator result (*this);
this_type result (*this);
increment();
return result;
}
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
friend bool operator== (const this_type& i, const this_type& i2)
{ return i.equal(i2); }
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
friend bool operator!= (const this_type& i, const this_type& i2)
{ return !(i == i2); }
/*
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
friend bool operator< (const this_type& i, const this_type& i2)
{ return i.less(i2); }
friend bool operator> (const this_type& i, const this_type& i2)
{ return i2 < i; }
friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
friend bool operator<= (const this_type& i, const this_type& i2)
{ return !(i > i2); }
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
friend bool operator>= (const this_type& i, const this_type& i2)
{ return !(i < i2); }
*/
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
friend std::ptrdiff_t operator- (const this_type& i, const this_type& i2)
{ return i2.distance_to(i); }
//Arithmetic
transform_iterator& operator+=(typename Iterator::difference_type off)
this_type& operator+=(std::ptrdiff_t off)
{ this->advance(off); return *this; }
transform_iterator operator+(typename Iterator::difference_type off) const
this_type operator+(std::ptrdiff_t off) const
{
transform_iterator other(*this);
this_type other(*this);
other.advance(off);
return other;
}
friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
friend this_type operator+(std::ptrdiff_t off, const this_type& right)
{ return right + off; }
transform_iterator& operator-=(typename Iterator::difference_type off)
this_type& operator-=(std::ptrdiff_t off)
{ this->advance(-off); return *this; }
transform_iterator operator-(typename Iterator::difference_type off) const
this_type operator-(std::ptrdiff_t off) const
{ return *this + (-off); }
typename UnaryFunction::result_type operator*() const
const T& operator*() const
{ return dereference(); }
operator_arrow_proxy<typename UnaryFunction::result_type>
operator->() const
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
const T* operator->() const
{ return &(dereference()); }
Iterator & base()
{ return m_it; }
const Iterator & base() const
{ return m_it; }
void construct_in_place(T* ptr)
{ (*m_pe)(ptr); }
private:
Iterator m_it;
std::ptrdiff_t m_num;
E * m_pe;
void increment()
{ ++m_it; }
{ --m_num; }
void decrement()
{ --m_it; }
{ ++m_num; }
bool equal(const transform_iterator &other) const
{ return m_it == other.m_it; }
bool equal(const this_type &other) const
{ return m_num == other.m_num; }
bool less(const transform_iterator &other) const
{ return other.m_it < m_it; }
bool less(const this_type &other) const
{ return other.m_num < m_num; }
typename UnaryFunction::result_type dereference() const
{ return UnaryFunction::operator()(*m_it); }
const T & dereference() const
{
static T dummy;
return dummy;
}
void advance(typename Iterator::difference_type n)
{ std::advance(m_it, n); }
void advance(std::ptrdiff_t n)
{ m_num -= n; }
typename Iterator::difference_type distance_to(const transform_iterator &other)const
{ return std::distance(other.m_it, m_it); }
std::ptrdiff_t distance_to(const this_type &other)const
{ return m_num - other.m_num; }
};
template <class Iterator, class UnaryFunc>
transform_iterator<Iterator, UnaryFunc>
make_transform_iterator(Iterator it, UnaryFunc fun)
{
return transform_iterator<Iterator, UnaryFunc>(it, fun);
}
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
} //namespace interprocess {
template<class T, class ...Args>
struct emplace_functor
{
typedef typename containers_detail::build_number_seq<sizeof...(Args)>::type index_tuple_t;
emplace_functor(Args&&... args)
: args_(args...)
{}
void operator()(T *ptr)
{ emplace_functor::inplace_impl(ptr, index_tuple_t()); }
template<int ...IdxPack>
void inplace_impl(T* ptr, const containers_detail::index_tuple<IdxPack...>&)
{ ::new(ptr) T(boost::interprocess::forward<Args>(containers_detail::get<IdxPack>(args_))...); }
containers_detail::tuple<Args&&...> args_;
};
#else
template<class T>
struct emplace_functor
{
emplace_functor()
{}
void operator()(T *ptr)
{ new(ptr) T(); }
};
#define BOOST_PP_LOCAL_MACRO(n) \
template <class T, BOOST_PP_ENUM_PARAMS(n, class P) > \
struct BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
{ \
BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
( BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _) ) \
: BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {} \
\
void operator()(T *ptr) \
{ \
new(ptr)T (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
} \
BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _) \
}; \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ITERATORS_HPP
#endif //#ifndef BOOST_CONTAINERS_DETAIL_ITERATORS_HPP

View File

@@ -0,0 +1,152 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP
#define BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <cstddef>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template <class T, T val>
struct integral_constant
{
static const T value = val;
typedef integral_constant<T,val> type;
};
template< bool C_ >
struct bool_ : integral_constant<bool, C_>
{
static const bool value = C_;
};
typedef bool_<true> true_;
typedef bool_<false> false_;
typedef true_ true_type;
typedef false_ false_type;
typedef char yes_type;
struct no_type
{
char padding[8];
};
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <class Cond, class T = void>
struct disable_if : public enable_if_c<!Cond::value, T> {};
template <class T, class U>
class is_convertible
{
typedef char true_t;
class false_t { char dummy[2]; };
static true_t dispatch(U);
static false_t dispatch(...);
static T trigger();
public:
enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) };
};
template<
bool C
, typename T1
, typename T2
>
struct if_c
{
typedef T1 type;
};
template<
typename T1
, typename T2
>
struct if_c<false,T1,T2>
{
typedef T2 type;
};
template<
typename T1
, typename T2
, typename T3
>
struct if_
{
typedef typename if_c<0 != T1::value, T2, T3>::type type;
};
template <class Pair>
struct select1st
// : public std::unary_function<Pair, typename Pair::first_type>
{
template<class OtherPair>
const typename Pair::first_type& operator()(const OtherPair& x) const
{ return x.first; }
const typename Pair::first_type& operator()(const typename Pair::first_type& x) const
{ return x; }
};
// identity is an extension: it is not part of the standard.
template <class T>
struct identity
// : public std::unary_function<T,T>
{
typedef T type;
const T& operator()(const T& x) const
{ return x; }
};
template<std::size_t S>
struct ls_zeros
{
static const std::size_t value = (S & std::size_t(1)) ? 0 : (1u + ls_zeros<(S >> 1u)>::value);
};
template<>
struct ls_zeros<0>
{
static const std::size_t value = 0;
};
template<>
struct ls_zeros<1>
{
static const std::size_t value = 0;
};
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#endif //#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP

View File

@@ -0,0 +1,554 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
#define BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/utilities.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <boost/interprocess/containers/container/detail/transform_iterator.hpp>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template<class VoidPointer>
class basic_multiallocation_slist
{
public:
typedef VoidPointer void_pointer;
private:
static VoidPointer &priv_get_ref(const VoidPointer &p)
{ return *static_cast<void_pointer*>(containers_detail::get_pointer(p)); }
basic_multiallocation_slist(basic_multiallocation_slist &);
basic_multiallocation_slist &operator=(basic_multiallocation_slist &);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_slist)
//!This iterator is returned by "allocate_many" functions so that
//!the user can access the multiple buffers allocated in a single call
class iterator
: public std::iterator<std::input_iterator_tag, char>
{
friend class basic_multiallocation_slist<void_pointer>;
void unspecified_bool_type_func() const {}
typedef void (iterator::*unspecified_bool_type)() const;
iterator(void_pointer node_range)
: next_node_(node_range)
{}
public:
typedef char value_type;
typedef value_type & reference;
typedef value_type * pointer;
iterator()
: next_node_(0)
{}
iterator &operator=(const iterator &other)
{ next_node_ = other.next_node_; return *this; }
public:
iterator& operator++()
{
next_node_ = *static_cast<void_pointer*>(containers_detail::get_pointer(next_node_));
return *this;
}
iterator operator++(int)
{
iterator result(*this);
++*this;
return result;
}
bool operator== (const iterator& other) const
{ return next_node_ == other.next_node_; }
bool operator!= (const iterator& other) const
{ return !operator== (other); }
reference operator*() const
{ return *static_cast<char*>(containers_detail::get_pointer(next_node_)); }
operator unspecified_bool_type() const
{ return next_node_? &iterator::unspecified_bool_type_func : 0; }
pointer operator->() const
{ return &(*(*this)); }
private:
void_pointer next_node_;
};
private:
iterator it_;
public:
basic_multiallocation_slist()
: it_(iterator())
{}
basic_multiallocation_slist(void_pointer p)
: it_(p ? iterator_to(p) : iterator())
{}
basic_multiallocation_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist) other)
: it_(iterator())
{ this->swap(other); }
basic_multiallocation_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist) other)
{
basic_multiallocation_slist tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
bool empty() const
{ return !it_; }
iterator before_begin() const
{ return iterator(void_pointer(const_cast<void*>(static_cast<const void*>(&it_.next_node_)))); }
iterator begin() const
{ return it_; }
iterator end() const
{ return iterator(); }
void clear()
{ this->it_.next_node_ = void_pointer(0); }
iterator insert_after(iterator it, void_pointer m)
{
priv_get_ref(m) = priv_get_ref(it.next_node_);
priv_get_ref(it.next_node_) = m;
return iterator(m);
}
void push_front(void_pointer m)
{
priv_get_ref(m) = this->it_.next_node_;
this->it_.next_node_ = m;
}
void pop_front()
{ ++it_; }
void *front() const
{ return containers_detail::get_pointer(it_.next_node_); }
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
{
if (after_this != before_begin && after_this != before_end && before_begin != before_end) {
void_pointer next_b = priv_get_ref(before_begin.next_node_);
void_pointer next_e = priv_get_ref(before_end.next_node_);
void_pointer next_p = priv_get_ref(after_this.next_node_);
priv_get_ref(before_begin.next_node_) = next_e;
priv_get_ref(before_end.next_node_) = next_p;
priv_get_ref(after_this.next_node_) = next_b;
}
}
void swap(basic_multiallocation_slist &other_chain)
{
std::swap(this->it_, other_chain.it_);
}
static iterator iterator_to(void_pointer p)
{ return iterator(p); }
void_pointer extract_data()
{
void_pointer ret = empty() ? void_pointer(0) : void_pointer(&*it_);
it_ = iterator();
return ret;
}
};
template<class VoidPointer>
class basic_multiallocation_cached_slist
{
private:
basic_multiallocation_slist<VoidPointer> slist_;
typename basic_multiallocation_slist<VoidPointer>::iterator last_;
basic_multiallocation_cached_slist(basic_multiallocation_cached_slist &);
basic_multiallocation_cached_slist &operator=(basic_multiallocation_cached_slist &);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_slist)
typedef typename basic_multiallocation_slist<VoidPointer>::void_pointer void_pointer;
typedef typename basic_multiallocation_slist<VoidPointer>::iterator iterator;
basic_multiallocation_cached_slist()
: slist_(), last_(slist_.before_begin())
{}
/*
basic_multiallocation_cached_slist(iterator first_node)
: slist_(first_node), last_(slist_.before_begin())
{
iterator end;
while(first_node != end){
++last_;
}
}*/
basic_multiallocation_cached_slist(void_pointer p1, void_pointer p2)
: slist_(p1), last_(p2 ? iterator_to(p2) : slist_.before_begin())
{}
basic_multiallocation_cached_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist) other)
: slist_(), last_(slist_.before_begin())
{ this->swap(other); }
basic_multiallocation_cached_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist) other)
{
basic_multiallocation_cached_slist tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
bool empty() const
{ return slist_.empty(); }
iterator before_begin() const
{ return slist_.before_begin(); }
iterator begin() const
{ return slist_.begin(); }
iterator end() const
{ return slist_.end(); }
iterator last() const
{ return last_; }
void clear()
{
slist_.clear();
last_ = slist_.before_begin();
}
iterator insert_after(iterator it, void_pointer m)
{
slist_.insert_after(it, m);
if(it == last_){
last_ = slist_.iterator_to(m);
}
return iterator_to(m);
}
void push_front(void_pointer m)
{ this->insert_after(this->before_begin(), m); }
void push_back(void_pointer m)
{ this->insert_after(last_, m); }
void pop_front()
{
if(last_ == slist_.begin()){
last_ = slist_.before_begin();
}
slist_.pop_front();
}
void *front() const
{ return slist_.front(); }
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
{
if(before_begin == before_end)
return;
if(after_this == last_){
last_ = before_end;
}
slist_.splice_after(after_this, before_begin, before_end);
}
void swap(basic_multiallocation_cached_slist &x)
{
slist_.swap(x.slist_);
using std::swap;
swap(last_, x.last_);
if(last_ == x.before_begin()){
last_ = this->before_begin();
}
if(x.last_ == this->before_begin()){
x.last_ = x.before_begin();
}
}
static iterator iterator_to(void_pointer p)
{ return basic_multiallocation_slist<VoidPointer>::iterator_to(p); }
std::pair<void_pointer, void_pointer> extract_data()
{
if(this->empty()){
return std::pair<void_pointer, void_pointer>(void_pointer(0), void_pointer(0));
}
else{
void_pointer p1 = slist_.extract_data();
void_pointer p2 = void_pointer(&*last_);
last_ = iterator();
return std::pair<void_pointer, void_pointer>(p1, p2);
}
}
};
template<class MultiallocatorCachedSlist>
class basic_multiallocation_cached_counted_slist
{
private:
MultiallocatorCachedSlist cached_slist_;
std::size_t size_;
basic_multiallocation_cached_counted_slist(basic_multiallocation_cached_counted_slist &);
basic_multiallocation_cached_counted_slist &operator=(basic_multiallocation_cached_counted_slist &);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_counted_slist)
typedef typename MultiallocatorCachedSlist::void_pointer void_pointer;
typedef typename MultiallocatorCachedSlist::iterator iterator;
basic_multiallocation_cached_counted_slist()
: cached_slist_(), size_(0)
{}
basic_multiallocation_cached_counted_slist(void_pointer p1, void_pointer p2, std::size_t n)
: cached_slist_(p1, p2), size_(n)
{}
basic_multiallocation_cached_counted_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist) other)
: cached_slist_(), size_(0)
{ this->swap(other); }
basic_multiallocation_cached_counted_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist) other)
{
basic_multiallocation_cached_counted_slist tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
basic_multiallocation_cached_counted_slist (MultiallocatorCachedSlist mem, std::size_t n)
: cached_slist_(boost::interprocess::move(mem)), size_(n)
{}
bool empty() const
{ return cached_slist_.empty(); }
std::size_t size() const
{ return size_; }
iterator before_begin() const
{ return cached_slist_.before_begin(); }
iterator begin() const
{ return cached_slist_.begin(); }
iterator end() const
{ return cached_slist_.end(); }
iterator last() const
{ return cached_slist_.last(); }
void clear()
{
cached_slist_.clear();
size_ = 0;
}
iterator insert_after(iterator it, void_pointer m)
{
iterator ret = cached_slist_.insert_after(it, m);
++size_;
return ret;
}
void push_front(void_pointer m)
{ this->insert_after(this->before_begin(), m); }
void push_back(void_pointer m)
{ this->insert_after(this->before_begin(), m); }
void pop_front()
{
cached_slist_.pop_front();
--size_;
}
void *front() const
{ return cached_slist_.front(); }
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x, iterator before_begin, iterator before_end)
{
std::size_t n = static_cast<std::size_t>(std::distance(before_begin, before_end));
this->splice_after(after_this, x, before_begin, before_end, n);
}
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x, iterator before_begin, iterator before_end, std::size_t n)
{
cached_slist_.splice_after(after_this, before_begin, before_end);
size_ += n;
x.size_ -= n;
}
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x)
{
cached_slist_.splice_after(after_this, x.before_begin(), x.last());
size_ += x.size_;
x.size_ = 0;
}
void swap(basic_multiallocation_cached_counted_slist &x)
{
cached_slist_.swap(x.cached_slist_);
using std::swap;
swap(size_, x.size_);
}
static iterator iterator_to(void_pointer p)
{ return MultiallocatorCachedSlist::iterator_to(p); }
std::pair<void_pointer, void_pointer> extract_data()
{
size_ = 0;
return cached_slist_.extract_data();
}
};
template<class T>
struct cast_functor
{
typedef typename containers_detail::add_reference<T>::type result_type;
result_type operator()(char &ptr) const
{ return *static_cast<T*>(static_cast<void*>(&ptr)); }
};
template<class MultiallocationChain, class T>
class transform_multiallocation_chain
{
private:
MultiallocationChain holder_;
typedef typename MultiallocationChain::void_pointer void_pointer;
typedef typename boost::pointer_to_other
<void_pointer, T>::type pointer;
transform_multiallocation_chain(transform_multiallocation_chain &);
transform_multiallocation_chain &operator=(transform_multiallocation_chain &);
static pointer cast(void_pointer p)
{
return pointer(static_cast<T*>(containers_detail::get_pointer(p)));
}
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(transform_multiallocation_chain)
typedef transform_iterator
< typename MultiallocationChain::iterator
, containers_detail::cast_functor <T> > iterator;
transform_multiallocation_chain(void_pointer p1, void_pointer p2, std::size_t n)
: holder_(p1, p2, n)
{}
transform_multiallocation_chain()
: holder_()
{}
transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain) other)
: holder_()
{ this->swap(other); }
transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(MultiallocationChain) other)
: holder_(boost::interprocess::move(other))
{}
transform_multiallocation_chain& operator=(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain) other)
{
transform_multiallocation_chain tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
void push_front(pointer mem)
{ holder_.push_front(mem); }
void swap(transform_multiallocation_chain &other_chain)
{ holder_.swap(other_chain.holder_); }
/*
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
{ holder_.splice_after(after_this.base(), before_begin.base(), before_end.base()); }
*/
void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_begin, iterator before_end, std::size_t n)
{ holder_.splice_after(after_this.base(), x.holder_, before_begin.base(), before_end.base(), n); }
void pop_front()
{ holder_.pop_front(); }
pointer front() const
{ return cast(holder_.front()); }
bool empty() const
{ return holder_.empty(); }
iterator before_begin() const
{ return iterator(holder_.before_begin()); }
iterator begin() const
{ return iterator(holder_.begin()); }
iterator end() const
{ return iterator(holder_.end()); }
iterator last() const
{ return iterator(holder_.last()); }
std::size_t size() const
{ return holder_.size(); }
void clear()
{ holder_.clear(); }
iterator insert_after(iterator it, pointer m)
{ return iterator(holder_.insert_after(it.base(), m)); }
static iterator iterator_to(pointer p)
{ return iterator(MultiallocationChain::iterator_to(p)); }
std::pair<void_pointer, void_pointer> extract_data()
{ return holder_.extract_data(); }
MultiallocationChain extract_multiallocation_chain()
{
return MultiallocationChain(boost::interprocess::move(holder_));
}
};
}}}
// namespace containers_detail {
// namespace interprocess_container {
// namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP

View File

@@ -4,36 +4,137 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_NODE_ALLOC_HPP_
#define BOOST_INTERPROCESS_DETAIL_NODE_ALLOC_HPP_
#ifndef BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
#define BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/algorithms.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <utility>
#include <functional>
#include <boost/interprocess/detail/move.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/interprocess/containers/container/detail/version_type.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <boost/interprocess/containers/container/detail/utilities.hpp>
#include <boost/interprocess/containers/container/detail/mpl.hpp>
#include <boost/interprocess/containers/container/detail/destroyers.hpp>
#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
#endif
#include <boost/interprocess/containers/container/detail/algorithms.hpp>
namespace boost {
namespace interprocess {
namespace detail {
namespace interprocess_container {
namespace containers_detail {
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an object using a STL allocator.
template <class Allocator>
struct scoped_deallocator
{
typedef typename Allocator::pointer pointer;
typedef containers_detail::integral_constant<unsigned,
boost::interprocess_container::containers_detail::
version<Allocator>::value> alloc_version;
typedef containers_detail::integral_constant<unsigned, 1> allocator_v1;
typedef containers_detail::integral_constant<unsigned, 2> allocator_v2;
private:
void priv_deallocate(allocator_v1)
{ m_alloc.deallocate(m_ptr, 1); }
void priv_deallocate(allocator_v2)
{ m_alloc.deallocate_one(m_ptr); }
scoped_deallocator(scoped_deallocator &);
scoped_deallocator& operator=(scoped_deallocator &);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(scoped_deallocator)
pointer m_ptr;
Allocator& m_alloc;
scoped_deallocator(pointer p, Allocator& a)
: m_ptr(p), m_alloc(a)
{}
~scoped_deallocator()
{ if (m_ptr)priv_deallocate(alloc_version()); }
scoped_deallocator(BOOST_INTERPROCESS_RV_REF(scoped_deallocator) o)
: m_ptr(o.m_ptr), m_alloc(o.m_alloc)
{ o.release(); }
pointer get() const
{ return m_ptr; }
void release()
{ m_ptr = 0; }
};
template <class A>
class allocator_destroyer_and_chain_builder
{
typedef typename A::value_type value_type;
typedef typename A::multiallocation_chain multiallocation_chain;
A & a_;
multiallocation_chain &c_;
public:
allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
: a_(a), c_(c)
{}
void operator()(const typename A::pointer &p)
{
value_type *vp = containers_detail::get_pointer(p);
vp->~value_type();
c_.push_front(vp);
}
};
template <class A>
class allocator_multialloc_chain_node_deallocator
{
typedef typename A::value_type value_type;
typedef typename A::multiallocation_chain multiallocation_chain;
typedef allocator_destroyer_and_chain_builder<A> chain_builder;
A & a_;
multiallocation_chain c_;
public:
allocator_multialloc_chain_node_deallocator(A &a)
: a_(a), c_()
{}
chain_builder get_chain_builder()
{ return chain_builder(a_, c_); }
~allocator_multialloc_chain_node_deallocator()
{
if(!c_.empty())
a_.deallocate_individual(boost::interprocess::move(c_));
}
};
template<class ValueCompare, class Node>
struct node_compare
@@ -66,18 +167,25 @@ struct node_alloc_holder
typedef typename A::template rebind<Node>::other NodeAlloc;
typedef A ValAlloc;
typedef typename NodeAlloc::pointer NodePtr;
typedef detail::scoped_deallocator<NodeAlloc> Deallocator;
typedef containers_detail::scoped_deallocator<NodeAlloc> Deallocator;
typedef typename NodeAlloc::size_type size_type;
typedef typename NodeAlloc::difference_type difference_type;
typedef detail::integral_constant<unsigned, 1> allocator_v1;
typedef detail::integral_constant<unsigned, 2> allocator_v2;
typedef detail::integral_constant<unsigned,
boost::interprocess::detail::
typedef containers_detail::integral_constant<unsigned, 1> allocator_v1;
typedef containers_detail::integral_constant<unsigned, 2> allocator_v2;
typedef containers_detail::integral_constant<unsigned,
boost::interprocess_container::containers_detail::
version<NodeAlloc>::value> alloc_version;
typedef typename ICont::iterator icont_iterator;
typedef typename ICont::const_iterator icont_citerator;
typedef allocator_destroyer<NodeAlloc> Destroyer;
private:
node_alloc_holder(node_alloc_holder&);
node_alloc_holder & operator=(node_alloc_holder&);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(node_alloc_holder)
node_alloc_holder(const ValAlloc &a)
: members_(a)
{}
@@ -86,32 +194,19 @@ struct node_alloc_holder
: members_(other.node_alloc())
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
node_alloc_holder(detail::moved_object<node_alloc_holder> other)
: members_(detail::move_impl(other.get().node_alloc()))
{ this->swap(other.get()); }
#else
node_alloc_holder(node_alloc_holder &&other)
: members_(detail::move_impl(other.node_alloc()))
node_alloc_holder(BOOST_INTERPROCESS_RV_REF(node_alloc_holder) other)
: members_(boost::interprocess::move(other.node_alloc()))
{ this->swap(other); }
#endif
template<class Pred>
node_alloc_holder(const ValAlloc &a, const Pred &c)
: members_(a, typename ICont::value_compare(c))
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Pred>
node_alloc_holder(detail::moved_object<ValAlloc> a, const Pred &c)
: members_(a.get(), typename ICont::value_compare(c))
{}
#else
template<class Pred>
node_alloc_holder(ValAlloc &&a, const Pred &c)
node_alloc_holder(BOOST_INTERPROCESS_RV_REF(ValAlloc) a, const Pred &c)
: members_(a, typename ICont::value_compare(c))
{}
#endif
template<class Pred>
node_alloc_holder(const node_alloc_holder &other, const Pred &c)
@@ -142,46 +237,27 @@ struct node_alloc_holder
void deallocate_one(NodePtr p, allocator_v2)
{ this->node_alloc().deallocate_one(p); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible1, class Convertible2>
static void construct(const NodePtr &ptr, detail::moved_object<std::pair<Convertible1, Convertible2> > value)
{
typedef typename Node::hook_type hook_type;
typedef typename Node::value_type::first_type first_type;
typedef typename Node::value_type::second_type second_type;
Node *nodeptr = detail::get_pointer(ptr);
//Hook constructor does not throw
new(static_cast<hook_type*>(nodeptr))hook_type();
//Now construct pair members_holder
value_type *valueptr = &nodeptr->get_data();
new((void*)&valueptr->first) first_type(detail::move_impl(value.get().first));
BOOST_TRY{
new((void*)&valueptr->second) second_type(detail::move_impl(value.get().second));
}
BOOST_CATCH(...){
valueptr->first.~first_type();
static_cast<hook_type*>(nodeptr)->~hook_type();
BOOST_RETHROW
}
BOOST_CATCH_END
}
#else
template<class Convertible1, class Convertible2>
static void construct(const NodePtr &ptr, std::pair<Convertible1, Convertible2> &&value)
static void construct(const NodePtr &ptr,
#ifdef BOOST_HAS_RVALUE_REFS
std::pair<Convertible1, Convertible2> &&
#else
boost::interprocess::rv<std::pair<Convertible1, Convertible2> > &
#endif
value)
{
typedef typename Node::hook_type hook_type;
typedef typename Node::value_type::first_type first_type;
typedef typename Node::value_type::second_type second_type;
Node *nodeptr = detail::get_pointer(ptr);
Node *nodeptr = containers_detail::get_pointer(ptr);
//Hook constructor does not throw
new(static_cast<hook_type*>(nodeptr))hook_type();
//Now construct pair members_holder
value_type *valueptr = &nodeptr->get_data();
new((void*)&valueptr->first) first_type(detail::move_impl(value.first));
new((void*)&valueptr->first) first_type(boost::interprocess::move(value.first));
BOOST_TRY{
new((void*)&valueptr->second) second_type(detail::move_impl(value.second));
new((void*)&valueptr->second) second_type(boost::interprocess::move(value.second));
}
BOOST_CATCH(...){
valueptr->first.~first_type();
@@ -190,44 +266,35 @@ struct node_alloc_holder
}
BOOST_CATCH_END
}
#endif
static void destroy(const NodePtr &ptr)
{ detail::get_pointer(ptr)->~Node(); }
{ containers_detail::get_pointer(ptr)->~Node(); }
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
Deallocator
#else
move_return<Deallocator>
#endif
create_node_and_deallocator()
Deallocator create_node_and_deallocator()
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
return node_deallocator;
return Deallocator(this->allocate_one(), this->node_alloc());
}
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
template<class ...Args>
static void construct(const NodePtr &ptr, Args &&...args)
{ new((void*)detail::get_pointer(ptr)) Node(detail::forward_impl<Args>(args)...); }
{ new((void*)containers_detail::get_pointer(ptr)) Node(boost::interprocess::forward<Args>(args)...); }
template<class ...Args>
NodePtr create_node(Args &&...args)
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
self_t::construct(p, detail::forward_impl<Args>(args)...);
self_t::construct(p, boost::interprocess::forward<Args>(args)...);
node_deallocator.release();
return (p);
}
#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
static void construct(const NodePtr &ptr)
{ new((void*)detail::get_pointer(ptr)) Node(); }
{ new((void*)containers_detail::get_pointer(ptr)) Node(); }
NodePtr create_node()
{
@@ -240,37 +307,37 @@ struct node_alloc_holder
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
void construct(const NodePtr &ptr, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
void construct(const NodePtr &ptr, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
new((void*)detail::get_pointer(ptr)) \
Node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
new((void*)containers_detail::get_pointer(ptr)) \
Node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
NodePtr create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
NodePtr create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
NodePtr p = this->allocate_one(); \
Deallocator node_deallocator(p, this->node_alloc()); \
self_t::construct(p, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
self_t::construct(p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
node_deallocator.release(); \
return (p); \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
template<class It>
NodePtr create_node_from_it(It it)
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
::boost::interprocess::construct_in_place(detail::get_pointer(p), it);
::boost::interprocess_container::construct_in_place(containers_detail::get_pointer(p), it);
node_deallocator.release();
return (p);
}
@@ -287,7 +354,7 @@ struct node_alloc_holder
NodeAlloc& other_alloc = x.node_alloc();
if (this_alloc != other_alloc){
detail::do_swap(this_alloc, other_alloc);
containers_detail::do_swap(this_alloc, other_alloc);
}
this->icont().swap(x.icont());
@@ -298,19 +365,19 @@ struct node_alloc_holder
(FwdIterator beg, difference_type n, Inserter inserter)
{
if(n){
typedef typename NodeAlloc::multiallocation_iterator multiallocation_iterator;
typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
//Try to allocate memory in a single block
multiallocation_iterator itbeg =
this->node_alloc().allocate_individual(n), itend, itold;
multiallocation_chain mem(this->node_alloc().allocate_individual(n));
int constructed = 0;
Node *p = 0;
BOOST_TRY{
for(difference_type i = 0; i < n; ++i, ++beg, --constructed){
p = &*itbeg;
++itbeg;
p = containers_detail::get_pointer(mem.front());
mem.pop_front();
//This can throw
boost::interprocess::construct_in_place(p, beg);
constructed = 0;
boost::interprocess_container::construct_in_place(p, beg);
++constructed;
//This can throw in some containers (predicate might throw)
inserter(*p);
@@ -320,7 +387,7 @@ struct node_alloc_holder
if(constructed){
this->destroy(p);
}
this->node_alloc().deallocate_many(itbeg);
this->node_alloc().deallocate_individual(boost::interprocess::move(mem));
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -334,8 +401,12 @@ struct node_alloc_holder
void clear(allocator_v2)
{
allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
this->icont().clear_and_dispose(chain_holder.get_chain_builder());
typename NodeAlloc::multiallocation_chain chain;
allocator_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain);
this->icont().clear_and_dispose(builder);
BOOST_STATIC_ASSERT((boost::interprocess::is_movable<typename NodeAlloc::multiallocation_chain>::value == true));
if(!chain.empty())
this->node_alloc().deallocate_individual(boost::interprocess::move(chain));
}
icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v1)
@@ -419,10 +490,10 @@ struct node_alloc_holder
{ return static_cast<const NodeAlloc &>(this->members_); }
};
} //namespace detail {
} //namespace interprocess {
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif // BOOST_INTERPROCESS_DETAIL_NODE_ALLOC_HPP_
#endif // BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_

View File

@@ -0,0 +1,189 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2009.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_CONTAINERS_DETAIL_PAIR_HPP
#define BOOST_CONTAINERS_CONTAINERS_DETAIL_PAIR_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/mpl.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <utility> //std::pair
#include <boost/interprocess/detail/move.hpp>
#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
#endif
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template <class T1, class T2>
struct pair
{
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(pair)
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
//std::pair compatibility
template <class D, class S>
pair(const std::pair<D, S>& p)
: first(p.first), second(p.second)
{}
//To resolve ambiguity with the variadic constructor of 1 argument
//and the previous constructor
pair(std::pair<T1, T2>& x)
: first(x.first), second(x.second)
{}
template <class D, class S>
pair(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(std::pair, D, S) p)
: first(boost::interprocess::move(p.first)), second(boost::interprocess::move(p.second))
{}
pair()
: first(), second()
{}
pair(const pair<T1, T2>& x)
: first(x.first), second(x.second)
{}
//To resolve ambiguity with the variadic constructor of 1 argument
//and the copy constructor
pair(pair<T1, T2>& x)
: first(x.first), second(x.second)
{}
pair(BOOST_INTERPROCESS_RV_REF(pair) p)
: first(boost::interprocess::move(p.first)), second(boost::interprocess::move(p.second))
{}
template <class D, class S>
pair(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(pair, D, S) p)
: first(boost::interprocess::move(p.first)), second(boost::interprocess::move(p.second))
{}
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
template<class U, class ...Args>
pair(U &&u, Args &&... args)
: first(boost::interprocess::forward<U>(u))
, second(boost::interprocess::forward<Args>(args)...)
{}
#else
template<class U>
pair( BOOST_CONTAINERS_PARAM(U, u)
#ifndef BOOST_HAS_RVALUE_REFS
, typename containers_detail::disable_if
< containers_detail::is_same<U, boost::interprocess::rv<pair> > >::type* = 0
#endif
)
: first(boost::interprocess::forward<U>(const_cast<U&>(u)))
{}
#define BOOST_PP_LOCAL_MACRO(n) \
template<class U, BOOST_PP_ENUM_PARAMS(n, class P)> \
pair(BOOST_CONTAINERS_PARAM(U, u) \
,BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
: first(boost::interprocess::forward<U>(const_cast<U&>(u))) \
, second(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \
{} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif
pair& operator=(BOOST_INTERPROCESS_RV_REF(pair) p)
{
first = boost::interprocess::move(p.first);
second = boost::interprocess::move(p.second);
return *this;
}
pair& operator=(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(std::pair, T1, T2) p)
{
first = boost::interprocess::move(p.first);
second = boost::interprocess::move(p.second);
return *this;
}
template <class D, class S>
pair& operator=(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(std::pair, D, S) p)
{
first = boost::interprocess::move(p.first);
second = boost::interprocess::move(p.second);
return *this;
}
void swap(pair& p)
{ std::swap(*this, p); }
};
template <class T1, class T2>
inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(x.first == y.first && x.second == y.second); }
template <class T1, class T2>
inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(x.first < y.first ||
(!(y.first < x.first) && x.second < y.second)); }
template <class T1, class T2>
inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(x == y)); }
template <class T1, class T2>
inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return y < x; }
template <class T1, class T2>
inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(x < y)); }
template <class T1, class T2>
inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(y < x)); }
template <class T1, class T2>
inline pair<T1, T2> make_pair(T1 x, T2 y)
{ return pair<T1, T2>(x, y); }
template <class T1, class T2>
inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
{
swap(x.first, y.first);
swap(x.second, y.second);
}
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_PAIR_HPP

View File

@@ -0,0 +1,101 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2008. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP
#define BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#error "This file is not needed when perfect forwarding is available"
#endif
#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#define BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS 10
//Note:
//We define template parameters as const references to
//be able to bind temporaries. After that we will un-const them.
//This cast is ugly but it is necessary until "perfect forwarding"
//is achieved in C++0x. Meanwhile, if we want to be able to
//bind rvalues with non-const references, we have to be ugly
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_CONTAINERS_PP_PARAM_LIST(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
//!
#else
#define BOOST_CONTAINERS_PP_PARAM_LIST(z, n, data) \
const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
//!
#endif
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_CONTAINERS_PARAM(U, u) \
U && u \
//!
#else
#define BOOST_CONTAINERS_PARAM(U, u) \
const U & u \
//!
#endif
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_CONTAINERS_AUX_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
//!
#else
#define BOOST_CONTAINERS_AUX_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_CONTAINERS_AUX_PARAM_INC(z, n, data) \
BOOST_PP_CAT(++m_p, n) \
//!
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \
//!
#else
#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
//!
#endif
#define BOOST_CONTAINERS_PP_PARAM_FORWARD(z, n, data) \
boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
//!
#define BOOST_CONTAINERS_PP_MEMBER_FORWARD(z, n, data) \
boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
//!
#define BOOST_CONTAINERS_PP_MEMBER_IT_FORWARD(z, n, data) \
BOOST_PP_CAT(*m_p, n) \
//!
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#else
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#error "This file is not needed when perfect forwarding is available"
#endif
#endif //#ifndef BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP

View File

@@ -0,0 +1,176 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP
#define BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <iterator>
namespace boost {
namespace interprocess_container {
template <class PseudoReference>
struct operator_arrow_proxy
{
operator_arrow_proxy(const PseudoReference &px)
: m_value(px)
{}
PseudoReference* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
mutable PseudoReference m_value;
};
template <class T>
struct operator_arrow_proxy<T&>
{
operator_arrow_proxy(T &px)
: m_value(px)
{}
T* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
mutable T &m_value;
};
template <class Iterator, class UnaryFunction>
class transform_iterator
: public UnaryFunction
, public std::iterator
< typename Iterator::iterator_category
, typename containers_detail::remove_reference<typename UnaryFunction::result_type>::type
, typename Iterator::difference_type
, operator_arrow_proxy<typename UnaryFunction::result_type>
, typename UnaryFunction::result_type>
{
public:
explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
: UnaryFunction(f), m_it(it)
{}
explicit transform_iterator()
: UnaryFunction(), m_it()
{}
//Constructors
transform_iterator& operator++()
{ increment(); return *this; }
transform_iterator operator++(int)
{
transform_iterator result (*this);
increment();
return result;
}
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
{ return i.equal(i2); }
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i == i2); }
/*
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
{ return i2 < i; }
friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i > i2); }
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i < i2); }
*/
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
transform_iterator& operator+=(typename Iterator::difference_type off)
{ this->advance(off); return *this; }
transform_iterator operator+(typename Iterator::difference_type off) const
{
transform_iterator other(*this);
other.advance(off);
return other;
}
friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
{ return right + off; }
transform_iterator& operator-=(typename Iterator::difference_type off)
{ this->advance(-off); return *this; }
transform_iterator operator-(typename Iterator::difference_type off) const
{ return *this + (-off); }
typename UnaryFunction::result_type operator*() const
{ return dereference(); }
operator_arrow_proxy<typename UnaryFunction::result_type>
operator->() const
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
Iterator & base()
{ return m_it; }
const Iterator & base() const
{ return m_it; }
private:
Iterator m_it;
void increment()
{ ++m_it; }
void decrement()
{ --m_it; }
bool equal(const transform_iterator &other) const
{ return m_it == other.m_it; }
bool less(const transform_iterator &other) const
{ return other.m_it < m_it; }
typename UnaryFunction::result_type dereference() const
{ return UnaryFunction::operator()(*m_it); }
void advance(typename Iterator::difference_type n)
{ std::advance(m_it, n); }
typename Iterator::difference_type distance_to(const transform_iterator &other)const
{ return std::distance(other.m_it, m_it); }
};
template <class Iterator, class UnaryFunc>
transform_iterator<Iterator, UnaryFunc>
make_transform_iterator(Iterator it, UnaryFunc fun)
{
return transform_iterator<Iterator, UnaryFunc>(it, fun);
}
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP

View File

@@ -4,7 +4,7 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//
@@ -39,21 +39,25 @@
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef BOOST_INTERPROCESS_TREE_HPP
#define BOOST_INTERPROCESS_TREE_HPP
#ifndef BOOST_CONTAINERS_TREE_HPP
#define BOOST_CONTAINERS_TREE_HPP
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/algorithms.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/interprocess/containers/detail/node_alloc_holder.hpp>
#include <boost/intrusive/rbtree.hpp>
#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
#include <boost/interprocess/detail/preprocessor.hpp>
#include <boost/interprocess/containers/container/detail/utilities.hpp>
#include <boost/interprocess/containers/container/detail/algorithms.hpp>
#include <boost/interprocess/containers/container/detail/node_alloc_holder.hpp>
#include <boost/interprocess/containers/container/detail/destroyers.hpp>
#include <boost/interprocess/containers/container/detail/pair.hpp>
#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
#endif
#include <utility> //std::pair
@@ -61,8 +65,8 @@
#include <algorithm>
namespace boost {
namespace interprocess {
namespace detail {
namespace interprocess_container {
namespace containers_detail {
template<class Key, class Value, class KeyCompare, class KeyOfValue>
struct value_compare_impl
@@ -91,10 +95,10 @@ struct value_compare_impl
template<class VoidPointer>
struct rbtree_hook
{
typedef typename bi::make_set_base_hook
< bi::void_pointer<VoidPointer>
, bi::link_mode<bi::normal_link>
, bi::optimize_size<true>
typedef typename containers_detail::bi::make_set_base_hook
< containers_detail::bi::void_pointer<VoidPointer>
, containers_detail::bi::link_mode<containers_detail::bi::normal_link>
, containers_detail::bi::optimize_size<true>
>::type type;
};
@@ -107,7 +111,7 @@ struct rbtree_type
template<class T1, class T2>
struct rbtree_type< std::pair<T1, T2> >
{
typedef detail::pair<T1, T2> type;
typedef pair<T1, T2> type;
};
template <class T, class VoidPointer>
@@ -121,28 +125,32 @@ struct rbtree_node
typedef rbtree_node<T, VoidPointer> node_type;
#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
rbtree_node()
: m_data()
{}
rbtree_node(const rbtree_node &other)
: m_data(other.m_data)
{}
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
rbtree_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
: m_data(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)) \
rbtree_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
: m_data(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \
{} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#else //#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
#else //#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
template<class ...Args>
rbtree_node(Args &&...args)
: m_data(detail::forward_impl<Args>(args)...)
: m_data(boost::interprocess::forward<Args>(args)...)
{}
#endif//#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif//#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
rbtree_node &operator=(const rbtree_node &other)
{ do_assign(other.m_data); return *this; }
@@ -170,7 +178,7 @@ struct rbtree_node
}
template<class A, class B>
void do_assign(const detail::pair<const A, B> &p)
void do_assign(const pair<const A, B> &p)
{
const_cast<A&>(m_data.first) = p.first;
m_data.second = p.second;
@@ -182,64 +190,58 @@ struct rbtree_node
public:
template<class Convertible>
static void construct(node_type *ptr
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE)
, const Convertible &value)
#else
, Convertible &&value)
#endif
{ new(ptr) node_type(detail::forward_impl<Convertible>(value)); }
static void construct(node_type *ptr, BOOST_INTERPROCESS_FWD_REF(Convertible) convertible)
{ new(ptr) node_type(boost::interprocess::forward<Convertible>(convertible)); }
};
}//namespace detail {
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) || !defined(BOOST_INTERPROCESS_RVALUE_PAIR)
}//namespace containers_detail {
#if !defined(BOOST_HAS_RVALUE_REFS)
template<class T, class VoidPointer>
struct has_own_construct_from_it
< boost::interprocess::detail::rbtree_node<T, VoidPointer> >
< boost::interprocess_container::containers_detail::rbtree_node<T, VoidPointer> >
{
static const bool value = true;
};
#endif
namespace detail {
namespace containers_detail {
template<class A, class ValueCompare>
struct intrusive_rbtree_type
{
typedef typename A::value_type value_type;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename A::pointer, void>::type void_pointer;
typedef typename detail::rbtree_node
typedef typename containers_detail::rbtree_node
<value_type, void_pointer> node_type;
typedef node_compare<ValueCompare, node_type> node_compare_type;
typedef typename bi::make_rbtree
typedef typename containers_detail::bi::make_rbtree
<node_type
,bi::compare<node_compare_type>
,bi::base_hook<typename rbtree_hook<void_pointer>::type>
,bi::constant_time_size<true>
,bi::size_type<typename A::size_type>
,containers_detail::bi::compare<node_compare_type>
,containers_detail::bi::base_hook<typename rbtree_hook<void_pointer>::type>
,containers_detail::bi::constant_time_size<true>
,containers_detail::bi::size_type<typename A::size_type>
>::type container_type;
typedef container_type type ;
};
} //namespace detail {
} //namespace containers_detail {
namespace detail {
namespace containers_detail {
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A>
class rbtree
: protected detail::node_alloc_holder
<A, typename detail::intrusive_rbtree_type
: protected containers_detail::node_alloc_holder
<A, typename containers_detail::intrusive_rbtree_type
<A, value_compare_impl<Key, Value, KeyCompare, KeyOfValue>
>::type
>
{
typedef typename detail::intrusive_rbtree_type
typedef typename containers_detail::intrusive_rbtree_type
<A, value_compare_impl
<Key, Value, KeyCompare, KeyOfValue>
>::type Icont;
typedef detail::node_alloc_holder<A, Icont> AllocHolder;
typedef containers_detail::node_alloc_holder<A, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr;
typedef rbtree < Key, Value, KeyOfValue
, KeyCompare, A> ThisType;
@@ -248,7 +250,7 @@ class rbtree
typedef typename AllocHolder::Node Node;
typedef typename Icont::iterator iiterator;
typedef typename Icont::const_iterator iconst_iterator;
typedef detail::allocator_destroyer<NodeAlloc> Destroyer;
typedef containers_detail::allocator_destroyer<NodeAlloc> Destroyer;
typedef typename AllocHolder::allocator_v1 allocator_v1;
typedef typename AllocHolder::allocator_v2 allocator_v2;
typedef typename AllocHolder::alloc_version alloc_version;
@@ -293,6 +295,8 @@ class rbtree
};
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(rbtree)
typedef Key key_type;
typedef Value value_type;
typedef A allocator_type;
@@ -450,15 +454,9 @@ class rbtree
(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
rbtree(detail::moved_object<rbtree> x)
: AllocHolder(x.get(), x.get().key_comp())
{ this->swap(x.get()); }
#else
rbtree(rbtree &&x)
rbtree(BOOST_INTERPROCESS_RV_REF(rbtree) x)
: AllocHolder(x, x.key_comp())
{ this->swap(x); }
#endif
~rbtree()
{} //AllocHolder clears the tree
@@ -488,13 +486,8 @@ class rbtree
return *this;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
rbtree& operator=(detail::moved_object<rbtree> mx)
{ this->clear(); this->swap(mx.get()); return *this; }
#else
rbtree& operator=(rbtree &&mx)
rbtree& operator=(BOOST_INTERPROCESS_RV_REF(rbtree) mx)
{ this->clear(); this->swap(mx); return *this; }
#endif
public:
// accessors:
@@ -583,14 +576,6 @@ class rbtree
void swap(ThisType& x)
{ AllocHolder::swap(x); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(detail::moved_object<rbtree> mt)
{ this->swap(mt.get()); }
#else
void swap(rbtree &&mt)
{ this->swap(mt); }
#endif
public:
typedef typename Icont::insert_commit_data insert_commit_data;
@@ -619,25 +604,14 @@ class rbtree
return iterator(it);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_unique_commit
(detail::moved_object<MovableConvertible> mv, insert_commit_data &data)
(BOOST_INTERPROCESS_FWD_REF(MovableConvertible) mv, insert_commit_data &data)
{
NodePtr tmp = AllocHolder::create_node(mv);
NodePtr tmp = AllocHolder::create_node(boost::interprocess::forward<MovableConvertible>(mv));
iiterator it(this->icont().insert_unique_commit(*tmp, data));
return iterator(it);
}
#else
template<class MovableConvertible>
iterator insert_unique_commit
(MovableConvertible && mv, insert_commit_data &data)
{
NodePtr tmp = AllocHolder::create_node(detail::forward_impl<MovableConvertible>(mv));
iiterator it(this->icont().insert_unique_commit(*tmp, data));
return iterator(it);
}
#endif
std::pair<iterator,bool> insert_unique(const value_type& v)
{
@@ -650,21 +624,8 @@ class rbtree
(this->insert_unique_commit(v, data), true);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
std::pair<iterator,bool> insert_unique(detail::moved_object<MovableConvertible> mv)
{
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(KeyOfValue()(mv.get()), data);
if(!ret.second)
return ret;
return std::pair<iterator,bool>
(this->insert_unique_commit(mv, data), true);
}
#else
template<class MovableConvertible>
std::pair<iterator,bool> insert_unique(MovableConvertible &&mv)
std::pair<iterator,bool> insert_unique(BOOST_INTERPROCESS_FWD_REF(MovableConvertible) mv)
{
insert_commit_data data;
std::pair<iterator,bool> ret =
@@ -672,9 +633,8 @@ class rbtree
if(!ret.second)
return ret;
return std::pair<iterator,bool>
(this->insert_unique_commit(detail::forward_impl<MovableConvertible>(mv), data), true);
(this->insert_unique_commit(boost::interprocess::forward<MovableConvertible>(mv), data), true);
}
#endif
private:
iterator emplace_unique_impl(NodePtr p)
@@ -705,31 +665,31 @@ class rbtree
public:
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
template <class... Args>
iterator emplace_unique(Args&&... args)
{ return this->emplace_unique_impl(AllocHolder::create_node(detail::forward_impl<Args>(args)...)); }
{ return this->emplace_unique_impl(AllocHolder::create_node(boost::interprocess::forward<Args>(args)...)); }
template <class... Args>
iterator emplace_hint_unique(const_iterator hint, Args&&... args)
{ return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(detail::forward_impl<Args>(args)...)); }
{ return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::interprocess::forward<Args>(args)...)); }
template <class... Args>
iterator emplace_equal(Args&&... args)
{
NodePtr p(AllocHolder::create_node(detail::forward_impl<Args>(args)...));
NodePtr p(AllocHolder::create_node(boost::interprocess::forward<Args>(args)...));
return iterator(this->icont().insert_equal(this->icont().end(), *p));
}
template <class... Args>
iterator emplace_hint_equal(const_iterator hint, Args&&... args)
{
NodePtr p(AllocHolder::create_node(detail::forward_impl<Args>(args)...));
NodePtr p(AllocHolder::create_node(boost::interprocess::forward<Args>(args)...));
return iterator(this->icont().insert_equal(hint.get(), *p));
}
#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
iterator emplace_unique()
{ return this->emplace_unique_impl(AllocHolder::create_node()); }
@@ -751,37 +711,37 @@ class rbtree
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
return this->emplace_unique_impl \
(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_hint_unique(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_hint_unique(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
return this->emplace_unique_hint_impl \
(hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
(hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
return iterator(this->icont().insert_equal(this->icont().end(), *p)); \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_hint_equal(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_hint_equal(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
return iterator(this->icont().insert_equal(hint.get(), *p)); \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
iterator insert_unique(const_iterator hint, const value_type& v)
{
@@ -793,30 +753,16 @@ class rbtree
return this->insert_unique_commit(v, data);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_unique(const_iterator hint, detail::moved_object<MovableConvertible> mv)
{
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(hint, KeyOfValue()(mv.get()), data);
if(!ret.second)
return ret.first;
return this->insert_unique_commit(mv, data);
}
#else
template<class MovableConvertible>
iterator insert_unique
(const_iterator hint, MovableConvertible &&mv)
iterator insert_unique(const_iterator hint, BOOST_INTERPROCESS_FWD_REF(MovableConvertible) mv)
{
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(hint, KeyOfValue()(mv), data);
if(!ret.second)
return ret.first;
return this->insert_unique_commit(detail::forward_impl<MovableConvertible>(mv), data);
return this->insert_unique_commit(boost::interprocess::forward<MovableConvertible>(mv), data);
}
#endif
template <class InputIterator>
void insert_unique(InputIterator first, InputIterator last)
@@ -840,21 +786,12 @@ class rbtree
return iterator(this->icont().insert_equal(this->icont().end(), *p));
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_equal(detail::moved_object<MovableConvertible> mv)
iterator insert_equal(BOOST_INTERPROCESS_FWD_REF(MovableConvertible) mv)
{
NodePtr p(AllocHolder::create_node(mv));
NodePtr p(AllocHolder::create_node(boost::interprocess::forward<MovableConvertible>(mv)));
return iterator(this->icont().insert_equal(this->icont().end(), *p));
}
#else
template<class MovableConvertible>
iterator insert_equal(MovableConvertible &&mv)
{
NodePtr p(AllocHolder::create_node(detail::forward_impl<MovableConvertible>(mv)));
return iterator(this->icont().insert_equal(this->icont().end(), *p));
}
#endif
iterator insert_equal(const_iterator hint, const value_type& v)
{
@@ -862,21 +799,12 @@ class rbtree
return iterator(this->icont().insert_equal(hint.get(), *p));
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_equal(const_iterator hint, detail::moved_object<MovableConvertible> mv)
iterator insert_equal(const_iterator hint, BOOST_INTERPROCESS_FWD_REF(MovableConvertible) mv)
{
NodePtr p(AllocHolder::create_node(mv));
NodePtr p(AllocHolder::create_node(boost::interprocess::forward<MovableConvertible>(mv)));
return iterator(this->icont().insert_equal(hint.get(), *p));
}
#else
template<class MovableConvertible>
iterator insert_equal(const_iterator hint, MovableConvertible &&mv)
{
NodePtr p(AllocHolder::create_node(detail::move_impl(mv)));
return iterator(this->icont().insert_equal(hint.get(), *p));
}
#endif
template <class InputIterator>
void insert_equal(InputIterator first, InputIterator last)
@@ -1066,46 +994,25 @@ swap(rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
x.swap(y);
}
} //namespace detail {
} //namespace containers_detail {
} //namespace interprocess_container {
//!This class is movable
template <class T, class V, class K, class C, class A>
struct is_movable<detail::rbtree<T, V, K, C, A> >
{
enum { value = true };
};
//!This class is movable
template <class T, class VoidPointer>
struct is_movable<detail::rbtree_node<T, VoidPointer> >
{
enum { value = true };
};
//!This class is movable
/*
template <class A, class C>
struct is_movable<detail::rbtree_alloc<A, C> >
{
enum { value = true };
};
*/
namespace interprocess {
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class K, class V, class KOV,
class C, class A>
struct has_trivial_destructor_after_move<detail::rbtree<K, V, KOV, C, A> >
class C, class A>
struct has_trivial_destructor_after_move
<boost::interprocess_container::containers_detail::rbtree<K, V, KOV, C, A> >
{
enum { value =
has_trivial_destructor<A>::value &&
has_trivial_destructor<C>::value };
static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
};
} //namespace interprocess {
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_TREE_HPP
#endif //BOOST_CONTAINERS_TREE_HPP

View File

@@ -0,0 +1,166 @@
//////////////////////////////////////////////////////////////////////////////
// (C) Copyright John Maddock 2000.
// (C) Copyright Ion Gaztanaga 2005-2008.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
// The alignment_of implementation comes from John Maddock's boost::alignment_of code
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
#define BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
struct nat{};
//boost::alignment_of yields to 10K lines of preprocessed code, so we
//need an alternative
template <typename T> struct alignment_of;
template <typename T>
struct alignment_of_hack
{
char c;
T t;
alignment_of_hack();
};
template <unsigned A, unsigned S>
struct alignment_logic
{
enum{ value = A < S ? A : S };
};
template< typename T >
struct alignment_of
{
enum{ value = alignment_logic
< sizeof(alignment_of_hack<T>) - sizeof(T)
, sizeof(T)>::value };
};
//This is not standard, but should work with all compilers
union max_align
{
char char_;
short short_;
int int_;
long long_;
#ifdef BOOST_HAS_LONG_LONG
long long long_long_;
#endif
float float_;
double double_;
long double long_double_;
void * void_ptr_;
};
template<class T>
struct remove_reference
{
typedef T type;
};
template<class T>
struct remove_reference<T&>
{
typedef T type;
};
template<class T>
struct is_reference
{
enum { value = false };
};
template<class T>
struct is_reference<T&>
{
enum { value = true };
};
template<class T>
struct is_pointer
{
enum { value = false };
};
template<class T>
struct is_pointer<T*>
{
enum { value = true };
};
template <typename T>
struct add_reference
{
typedef T& type;
};
template<class T>
struct add_reference<T&>
{
typedef T& type;
};
template<>
struct add_reference<void>
{
typedef nat &type;
};
template<>
struct add_reference<const void>
{
typedef const nat &type;
};
template <class T>
struct add_const_reference
{ typedef const T &type; };
template <class T>
struct add_const_reference<T&>
{ typedef T& type; };
template <typename T, typename U>
struct is_same
{
typedef char yes_type;
struct no_type
{
char padding[8];
};
template <typename V>
static yes_type is_same_tester(V*, V*);
static no_type is_same_tester(...);
static T *t;
static U *u;
static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u));
};
} // namespace containers_detail
} //namespace interprocess_container {
} //namespace boost {
#endif //#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
#include <boost/interprocess/containers/container/detail/config_end.hpp>

View File

@@ -0,0 +1,95 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_UTILITIES_HPP
#define BOOST_CONTAINERS_DETAIL_UTILITIES_HPP
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <cstdio>
#include <algorithm>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template <class SizeType>
SizeType
get_next_capacity(const SizeType max_size
,const SizeType capacity
,const SizeType n)
{
// if (n > max_size - capacity)
// throw std::length_error("get_next_capacity");
const SizeType m3 = max_size/3;
if (capacity < m3)
return capacity + max_value(3*(capacity+1)/5, n);
if (capacity < m3*2)
return capacity + max_value((capacity+1)/2, n);
return max_size;
}
template<class T>
const T &max_value(const T &a, const T &b)
{ return a > b ? a : b; }
template<class T>
const T &min_value(const T &a, const T &b)
{ return a < b ? a : b; }
template<class SmartPtr>
struct smart_ptr_type
{
typedef typename SmartPtr::value_type value_type;
typedef value_type *pointer;
static pointer get (const SmartPtr &smartptr)
{ return smartptr.get();}
};
template<class T>
struct smart_ptr_type<T*>
{
typedef T value_type;
typedef value_type *pointer;
static pointer get (pointer ptr)
{ return ptr;}
};
//!Overload for smart pointers to avoid ADL problems with get_pointer
template<class Ptr>
inline typename smart_ptr_type<Ptr>::pointer
get_pointer(const Ptr &ptr)
{ return smart_ptr_type<Ptr>::get(ptr); }
//!To avoid ADL problems with swap
template <class T>
inline void do_swap(T& x, T& y)
{
using std::swap;
swap(x, y);
}
template <std::size_t OrigSize, std::size_t RoundTo>
struct ct_rounded_size
{
enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
};
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_UTILITIES_HPP

View File

@@ -0,0 +1,43 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2009.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP
#define BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template<class T>
struct value_init
{
value_init()
: m_t()
{}
T m_t;
};
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP

View File

@@ -0,0 +1,153 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2008. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
#define BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <cstddef> //std::size_t
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template<typename... Values>
class tuple;
template<> class tuple<>
{};
template<typename Head, typename... Tail>
class tuple<Head, Tail...>
: private tuple<Tail...>
{
typedef tuple<Tail...> inherited;
public:
tuple() { }
// implicit copy-constructor is okay
// Construct tuple from separate arguments.
tuple(typename add_const_reference<Head>::type v,
typename add_const_reference<Tail>::type... vtail)
: inherited(vtail...), m_head(v)
{}
// Construct tuple from another tuple.
template<typename... VValues>
tuple(const tuple<VValues...>& other)
: m_head(other.head()), inherited(other.tail())
{}
template<typename... VValues>
tuple& operator=(const tuple<VValues...>& other)
{
m_head = other.head();
tail() = other.tail();
return this;
}
typename add_reference<Head>::type head() { return m_head; }
typename add_reference<const Head>::type head() const { return m_head; }
inherited& tail() { return *this; }
const inherited& tail() const { return *this; }
protected:
Head m_head;
};
template<typename... Values>
tuple<Values&&...> tie_forward(Values&&... values)
{ return tuple<Values&&...>(values...); }
template<int I, typename Tuple>
struct tuple_element;
template<int I, typename Head, typename... Tail>
struct tuple_element<I, tuple<Head, Tail...> >
{
typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
};
template<typename Head, typename... Tail>
struct tuple_element<0, tuple<Head, Tail...> >
{
typedef Head type;
};
template<int I, typename Tuple>
class get_impl;
template<int I, typename Head, typename... Values>
class get_impl<I, tuple<Head, Values...> >
{
typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
typedef get_impl<I-1, tuple<Values...> > Next;
public:
typedef typename add_reference<Element>::type type;
typedef typename add_const_reference<Element>::type const_type;
static type get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
static const_type get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
};
template<typename Head, typename... Values>
class get_impl<0, tuple<Head, Values...> >
{
public:
typedef typename add_reference<Head>::type type;
typedef typename add_const_reference<Head>::type const_type;
static type get(tuple<Head, Values...>& t) { return t.head(); }
static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
};
template<int I, typename... Values>
typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
{ return get_impl<I, tuple<Values...> >::get(t); }
template<int I, typename... Values>
typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
{ return get_impl<I, tuple<Values...> >::get(t); }
////////////////////////////////////////////////////
// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
// be used to "unpack" into comma-separated values
// in a function call.
////////////////////////////////////////////////////
template<int... Indexes>
struct index_tuple{};
template<std::size_t Num, typename Tuple = index_tuple<> >
struct build_number_seq;
template<std::size_t Num, int... Indexes>
struct build_number_seq<Num, index_tuple<Indexes...> >
: build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
{};
template<int... Indexes>
struct build_number_seq<0, index_tuple<Indexes...> >
{ typedef index_tuple<Indexes...> type; };
}}} //namespace boost { namespace interprocess_container { namespace containers_detail {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP

View File

@@ -4,7 +4,7 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//
@@ -13,22 +13,22 @@
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_VERSION_TYPE_HPP
#define BOOST_INTERPROCESS_DETAIL_VERSION_TYPE_HPP
#ifndef BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP
#define BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/containers/container/detail/mpl.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
namespace boost{
namespace interprocess{
namespace detail{
namespace interprocess_container {
namespace containers_detail {
//using namespace boost;
template <class T, unsigned V>
struct version_type
: public detail::integral_constant<unsigned, V>
: public containers_detail::integral_constant<unsigned, V>
{
typedef T type;
@@ -38,7 +38,7 @@ struct version_type
namespace impl{
template <class T,
bool = detail::is_convertible<version_type<T, 0>, typename T::version>::value>
bool = containers_detail::is_convertible<version_type<T, 0>, typename T::version>::value>
struct extract_version
{
static const unsigned value = 1;
@@ -78,12 +78,12 @@ struct version<T, true>
template <class T>
struct version
: public detail::integral_constant<unsigned, impl::version<T>::value>
: public containers_detail::integral_constant<unsigned, impl::version<T>::value>
{
};
} //namespace detail{
} //namespace interprocess{
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost{
#endif //#define BOOST_INTERPROCESS_DETAIL_VERSION_TYPE_HPP
#endif //#define BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP

View File

@@ -0,0 +1,24 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP
#define BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)\
&& !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
#define BOOST_CONTAINERS_PERFECT_FORWARDING
#endif
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2009. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP
#define BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/pair.hpp>
namespace boost {
namespace interprocess {
using boost::interprocess_container::containers_detail::pair;
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2009. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP
#define BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/stable_vector.hpp>
namespace boost {
namespace interprocess {
using boost::interprocess_container::stable_vector;
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2009. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
#define BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/version_type.hpp>
namespace boost {
namespace interprocess {
using boost::interprocess_container::containers_detail::version_type;
using boost::interprocess_container::containers_detail::version;
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP

View File

@@ -48,7 +48,7 @@ inline boost::uint32_t atomic_cas32
} //namespace interprocess{
} //namespace boost{
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
#include <boost/interprocess/detail/win32_api.hpp>

View File

@@ -24,7 +24,12 @@ namespace detail{
class file_wrapper
{
/// @cond
file_wrapper(file_wrapper&);
file_wrapper & operator=(file_wrapper&);
/// @endcond
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(file_wrapper)
//!Default constructor.
//!Represents an empty file_wrapper.
@@ -49,34 +54,18 @@ class file_wrapper
//!Moves the ownership of "moved"'s file to *this.
//!After the call, "moved" does not represent any file.
//!Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
file_wrapper
(detail::moved_object<file_wrapper> moved)
{ this->swap(moved.get()); }
#else
file_wrapper(file_wrapper &&moved)
file_wrapper(BOOST_INTERPROCESS_RV_REF(file_wrapper) moved)
{ this->swap(moved); }
#endif
//!Moves the ownership of "moved"'s file to *this.
//!After the call, "moved" does not represent any file.
//!Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
file_wrapper &operator=
(detail::moved_object<file_wrapper> moved)
file_wrapper &operator=(BOOST_INTERPROCESS_RV_REF(file_wrapper) moved)
{
file_wrapper tmp(moved);
file_wrapper tmp(boost::interprocess::move(moved));
this->swap(tmp);
return *this;
}
#else
file_wrapper &operator=(file_wrapper &&moved)
{
file_wrapper tmp(detail::move_impl(moved));
this->swap(tmp);
return *this;
}
#endif
//!Swaps to file_wrappers.
//!Does not throw

View File

@@ -98,7 +98,7 @@ class basic_managed_memory_impl
segment_manager::char_ptr_holder_t char_ptr_holder_t;
//Experimental. Don't use.
typedef typename segment_manager::multiallocation_iterator multiallocation_iterator;
typedef typename segment_manager::multiallocation_chain multiallocation_chain;
/// @endcond
@@ -291,7 +291,7 @@ class basic_managed_memory_impl
template<class T>
std::pair<T *, bool>
allocation_command (allocation_type command, std::size_t limit_size,
allocation_command (boost::interprocess::allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
T *reuse_ptr = 0)
{
@@ -310,21 +310,25 @@ class basic_managed_memory_impl
//Experimental. Don't use.
//!Allocates n_elements of elem_size bytes.
multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements)
multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t num_elements)
{ return mp_header->allocate_many(elem_bytes, num_elements); }
//!Allocates n_elements, each one of elem_sizes[i] bytes.
multiallocation_iterator allocate_many(const std::size_t *elem_sizes, std::size_t n_elements)
multiallocation_chain allocate_many(const std::size_t *elem_sizes, std::size_t n_elements)
{ return mp_header->allocate_many(elem_sizes, n_elements); }
//!Allocates n_elements of elem_size bytes.
multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements, std::nothrow_t nothrow)
multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t num_elements, std::nothrow_t nothrow)
{ return mp_header->allocate_many(elem_bytes, num_elements, nothrow); }
//!Allocates n_elements, each one of elem_sizes[i] bytes.
multiallocation_iterator allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::nothrow_t nothrow)
multiallocation_chain allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::nothrow_t nothrow)
{ return mp_header->allocate_many(elem_sizes, n_elements, nothrow); }
//!Allocates n_elements, each one of elem_sizes[i] bytes.
void deallocate_many(multiallocation_chain chain)
{ return mp_header->deallocate_many(boost::interprocess::move(chain)); }
/// @endcond
//!Marks previously allocated memory as free. Never throws.

View File

@@ -315,21 +315,21 @@ class basic_managed_multi_shared_memory
case create_open_func::DoCreate:
{
managed_impl shm(create_only, name, size, read_write, addr, func);
mshm = detail::move_impl(shm);
mshm = boost::interprocess::move(shm);
}
break;
case create_open_func::DoOpen:
{
managed_impl shm(open_only, name,read_write, addr, func);
mshm = detail::move_impl(shm);
mshm = boost::interprocess::move(shm);
}
break;
case create_open_func::DoOpenOrCreate:
{
managed_impl shm(open_or_create, name, size, read_write, addr, func);
mshm = detail::move_impl(shm);
mshm = boost::interprocess::move(shm);
}
break;
@@ -339,7 +339,7 @@ class basic_managed_multi_shared_memory
}
//This can throw.
m_shmem_list.push_back(detail::move_impl(mshm));
m_shmem_list.push_back(boost::interprocess::move(mshm));
return true;
}
BOOST_CATCH(const std::bad_alloc&){

View File

@@ -37,8 +37,8 @@ template<class DeviceAbstraction, bool FileBased = true>
class managed_open_or_create_impl
{
//Non-copyable
managed_open_or_create_impl(const managed_open_or_create_impl &);
managed_open_or_create_impl &operator=(const managed_open_or_create_impl &);
managed_open_or_create_impl(managed_open_or_create_impl &);
managed_open_or_create_impl &operator=(managed_open_or_create_impl &);
enum
{
@@ -49,6 +49,7 @@ class managed_open_or_create_impl
};
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(managed_open_or_create_impl)
static const std::size_t
ManagedOpenOrCreateUserOffset =
@@ -154,34 +155,16 @@ class managed_open_or_create_impl
, construct_func);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
managed_open_or_create_impl(detail::moved_object<managed_open_or_create_impl> moved)
{ this->swap(moved.get()); }
#else
managed_open_or_create_impl(managed_open_or_create_impl &&moved)
managed_open_or_create_impl(BOOST_INTERPROCESS_RV_REF(managed_open_or_create_impl) moved)
{ this->swap(moved); }
#endif
//!Move assignment. If *this owns a memory mapped region, it will be
//!destroyed and it will take ownership of "other"'s memory mapped region.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
managed_open_or_create_impl &operator=(detail::moved_object<managed_open_or_create_impl> moved)
managed_open_or_create_impl &operator=(BOOST_INTERPROCESS_RV_REF(managed_open_or_create_impl) moved)
{
managed_open_or_create_impl tmp(moved);
managed_open_or_create_impl tmp(boost::interprocess::move(moved));
this->swap(tmp);
return *this;
}
#else
managed_open_or_create_impl &operator=(managed_open_or_create_impl &&moved)
{
managed_open_or_create_impl tmp(detail::move_impl(moved));
this->swap(tmp);
return *this;
}
#endif
~managed_open_or_create_impl()
{}
@@ -437,20 +420,6 @@ inline void swap(managed_open_or_create_impl<DeviceAbstraction> &x
} //namespace detail {
///@cond
//!Trait class to detect if a type is
//!movable
template<class DeviceAbstraction>
struct is_movable<detail::managed_open_or_create_impl<DeviceAbstraction> >
{
enum { value = true };
};
///@endcond
} //namespace interprocess {
} //namespace boost {

View File

@@ -1,175 +1,747 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//
// Parts of this file come from Adobe's Move library:
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
// or a copy at http://stlab.adobe.com/licenses.html)
//
//////////////////////////////////////////////////////////////////////////////
//! \file
#ifndef BOOST_INTERPROCESS_MOVE_HPP
#define BOOST_INTERPROCESS_MOVE_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/detail/mpl.hpp>
//!\file
//!Describes a function and a type to emulate move semantics.
#include <boost/config.hpp>
#include <algorithm> //copy, copy_backward
#include <memory> //uninitialized_copy
#include <iterator> //std::iterator
#include <boost/mpl/if.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
namespace boost {
namespace interprocess {
namespace move_detail {
//!Trait class to detect if a type is
//!movable
template <class T>
struct is_movable
struct identity
{
enum { value = false };
typedef T type;
};
template <class T, class U>
class is_convertible
{
typedef char true_t;
class false_t { char dummy[2]; };
static true_t dispatch(U);
static false_t dispatch(...);
static T trigger();
public:
enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) };
};
} //namespace move_detail {
} //namespace interprocess {
} //namespace boost {
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#if !defined(BOOST_HAS_RVALUE_REFS) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
namespace boost {
namespace interprocess {
namespace detail {
//!An object that represents a
//!moved object.
template<class T>
struct moved_object
{
moved_object(const T &obj)
: m_obj(const_cast<T *>(&obj))
{}
T &get() const
{ return *m_obj; }
private:
T *m_obj;
};
// Metafunction that, given movable T, provides move_source<T>, else T&.
template <typename T>
struct move_type
//////////////////////////////////////////////////////////////////////////////
//
// struct rv
//
//////////////////////////////////////////////////////////////////////////////
template <class T>
class rv : public T
{
public: // metafunction result
typedef typename if_<is_movable<T>, moved_object<T>, T&>::type type;
};
template <typename T>
class move_return
{
typedef moved_object<T> moved_type;
private:
mutable T m_moved;
rv();
~rv();
rv(rv const&);
void operator=(rv const&);
public:
typedef T type;
move_return(const T& returned)
: m_moved(moved_object<T>(returned))
{}
move_return(const move_return& operand)
: m_moved(const_cast<move_return&>(operand))
{}
operator moved_type() const
{ return moved_type(m_moved); }
//T &get() { return *this; }
};
template <typename T>
struct return_type
//////////////////////////////////////////////////////////////////////////////
//
// move_detail::is_rv
//
//////////////////////////////////////////////////////////////////////////////
namespace move_detail {
template <class T>
struct is_rv
{
public: // metafunction result
typedef typename if_<is_movable<T>, move_return<T>, T>::type type;
static const bool value = false;
};
} //namespace detail {
} //namespace interprocess {
} //namespace boost {
template <class T>
struct is_rv< rv<T> >
{
static const bool value = true;
};
namespace boost {
namespace interprocess {
} //namespace move_detail {
namespace detail{
//////////////////////////////////////////////////////////////////////////////
//
// is_movable
//
//////////////////////////////////////////////////////////////////////////////
template<class T>
class is_movable
{
public:
static const bool value = move_detail::is_convertible<T, rv<T>&>::value;
};
//!A function that converts an object to a moved object so that
//!it can match a function taking a detail::moved_object object.
template<class Object>
typename detail::move_type<Object>::type move_impl(const Object &object)
{
typedef typename detail::move_type<Object>::type type;
return type(object);
template<class T>
class is_movable< rv<T> >
{
public:
static const bool value = false;
};
//////////////////////////////////////////////////////////////////////////////
//
// move()
//
//////////////////////////////////////////////////////////////////////////////
template <class T>
typename boost::disable_if<is_movable<T>, T&>::type move(T& x)
{
return x;
}
template <class T>
inline const T& forward_impl(const T &t)
{ return t; }
typename enable_if<is_movable<T>, rv<T>&>::type move(T& x)
{
return reinterpret_cast<rv<T>& >(x);
}
template <class T>
inline T& forward_impl(T &t)
{ return t; }
typename enable_if<is_movable<T>, rv<T>&>::type move(const rv<T>& x)
{
return const_cast<rv<T>& >(x);
}
//////////////////////////////////////////////////////////////////////////////
//
// forward()
//
//////////////////////////////////////////////////////////////////////////////
template <class T>
inline detail::moved_object<T> forward_impl(detail::moved_object<T> &t)
{ return t; }
typename enable_if<boost::interprocess::move_detail::is_rv<T>, T &>::type
forward(const typename move_detail::identity<T>::type &x)
{
return const_cast<T&>(x);
}
} //namespace detail {
/*
template <class T>
typename enable_if<boost::interprocess::move_detail::is_rv<T>, T &>::type
forward(typename move_detail::identity<T>::type &x)
{
return x;
}
//!A function that converts an object to a moved object so that
//!it can match a function taking a detail::moved_object object.
template<class Object>
typename detail::move_type<Object>::type move(const Object &object)
{ return detail::move_impl(object); }
template <class T>
typename disable_if<boost::interprocess::move_detail::is_rv<T>, T &>::type
forward(typename move_detail::identity<T>::type &x)
{
return x;
}
*/
template <class T>
typename disable_if<boost::interprocess::move_detail::is_rv<T>, const T &>::type
forward(const typename move_detail::identity<T>::type &x)
{
return x;
}
//////////////////////////////////////////////////////////////////////////////
//
// BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION
//
//////////////////////////////////////////////////////////////////////////////
#define BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(TYPE)\
operator boost::interprocess::rv<TYPE>&() \
{ return reinterpret_cast<boost::interprocess::rv<TYPE>& >(*this); }\
//
#define BOOST_INTERPROCESS_RV_REF(TYPE)\
boost::interprocess::rv< TYPE >& \
//
#define BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
boost::interprocess::rv< TYPE<ARG1, ARG2> >& \
//
#define BOOST_INTERPROCESS_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
boost::interprocess::rv< TYPE<ARG1, ARG2, ARG3> >& \
//
#define BOOST_INTERPROCESS_FWD_REF(TYPE)\
const TYPE & \
//
} //namespace interprocess {
} //namespace boost {
} //namespace boost
#else //#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
#else //BOOST_HAS_RVALUE_REFS
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/type_traits/remove_reference.hpp>
namespace boost {
namespace interprocess {
namespace detail {
//////////////////////////////////////////////////////////////////////////////
//
// is_movable
//
//////////////////////////////////////////////////////////////////////////////
template <class T>
inline typename detail::remove_reference<T>::type&& move_impl(T&& t)
//! For compilers with rvalue references, this traits class returns true
//! if T && is convertible to T.
//!
//! For other compilers returns true if T is convertible to <i>boost::interprocess::rv<T>&</i>
template<class T>
class is_movable
{
public:
static const bool value = move_detail::is_convertible<T&&, T>::value;
};
//////////////////////////////////////////////////////////////////////////////
//
// move
//
//////////////////////////////////////////////////////////////////////////////
#if defined(BOOST_MOVE_DOXYGEN_INVOKED)
//! This function provides a way to convert a reference into a rvalue reference
//! in compilers with rvalue reference. For other compilers converts T & into
//! <i>boost::interprocess::rv<T> &</i> so that move emulation is activated.
template <class T> inline
rvalue_reference move (input_reference);
#else
template <class T> inline
typename remove_reference<T>::type&& move(T&& t)
{ return t; }
#endif
template <class T>
inline T&& forward_impl(typename detail::identity<T>::type&& t)
//////////////////////////////////////////////////////////////////////////////
//
// forward
//
//////////////////////////////////////////////////////////////////////////////
#if defined(BOOST_MOVE_DOXYGEN_INVOKED)
//! This function provides limited form of forwarding that is usually enough for
//! in-place construction and avoids the exponential overloading necessary for
//! perfect forwarding in C++03.
//!
//! For compilers with rvalue references this function provides perfect forwarding.
//!
//! Otherwise:
//! * If input_reference binds to const boost::interprocess::rv<T> & then it output_reference is
//! boost::rev<T> &
//!
//! * Else, input_reference is equal to output_reference is equal to input_reference.
template <class T> inline output_reference forward(input_reference);
#else
template <class T> inline
T&& forward (typename move_detail::identity<T>::type&& t)
{ return t; }
#endif
} //namespace detail {
//////////////////////////////////////////////////////////////////////////////
//
// BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION
//
//////////////////////////////////////////////////////////////////////////////
template <class T>
inline typename detail::remove_reference<T>::type&& move(T&& t)
{ return t; }
//! This macro expands to nothing for compilers with rvalue references.
//! Otherwise expands to:
//! \code
//! operator boost::interprocess::rv<TYPE>&()
//! { return static_cast<boost::interprocess::rv<TYPE>& >(*this); }
//! \endcode
#define BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(TYPE)\
//
#define BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
TYPE<ARG1, ARG2> && \
//
#define BOOST_INTERPROCESS_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
TYPE<ARG1, ARG2, ARG3> && \
//
//! This macro expands to <i>T&&</i> for compilers with rvalue references.
//! Otherwise expands to <i>boost::interprocess::rv<T> &</i>.
#define BOOST_INTERPROCESS_RV_REF(TYPE)\
TYPE && \
//
//! This macro expands to <i>T&&</i> for compilers with rvalue references.
//! Otherwise expands to <i>const T &</i>.
#define BOOST_INTERPROCESS_FWD_REF(TYPE)\
TYPE && \
//
} //namespace interprocess {
} //namespace boost {
#endif //#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
#endif //BOOST_HAS_RVALUE_REFS
#include <boost/interprocess/detail/config_end.hpp>
namespace boost {
namespace interprocess {
#endif //#ifndef BOOST_INTERPROCESS_MOVE_HPP
//////////////////////////////////////////////////////////////////////////////
//
// move_iterator
//
//////////////////////////////////////////////////////////////////////////////
//! Class template move_iterator is an iterator adaptor with the same behavior
//! as the underlying iterator except that its dereference operator implicitly
//! converts the value returned by the underlying iterator's dereference operator
//! to an rvalue reference. Some generic algorithms can be called with move
//! iterators to replace copying with moving.
template <class It>
class move_iterator
{
public:
typedef It iterator_type;
typedef typename std::iterator_traits<iterator_type>::value_type value_type;
#if defined(BOOST_HAS_RVALUE_REFS) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
typedef value_type && reference;
#else
typedef typename boost::mpl::if_
< boost::interprocess::is_movable<value_type>
, boost::interprocess::rv<value_type>&
, value_type & >::type reference;
#endif
typedef typename std::iterator_traits<iterator_type>::pointer pointer;
typedef typename std::iterator_traits<iterator_type>::difference_type difference_type;
typedef typename std::iterator_traits<iterator_type>::iterator_category iterator_category;
move_iterator()
{}
explicit move_iterator(It i)
: m_it(i)
{}
template <class U>
move_iterator(const move_iterator<U>& u)
: m_it(u.base())
{}
iterator_type base() const
{ return m_it; }
reference operator*() const
{
#if defined(BOOST_HAS_RVALUE_REFS)
return *m_it;
#else
return boost::interprocess::move(*m_it);
#endif
}
pointer operator->() const
{ return m_it; }
move_iterator& operator++()
{ ++m_it; return *this; }
move_iterator<iterator_type> operator++(int)
{ move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; }
move_iterator& operator--()
{ --m_it; return *this; }
move_iterator<iterator_type> operator--(int)
{ move_iterator<iterator_type> tmp(*this); --(*this); return tmp; }
move_iterator<iterator_type> operator+ (difference_type n) const
{ return move_iterator<iterator_type>(m_it + n); }
move_iterator& operator+=(difference_type n)
{ m_it += n; return *this; }
move_iterator<iterator_type> operator- (difference_type n) const
{ return move_iterator<iterator_type>(m_it - n); }
move_iterator& operator-=(difference_type n)
{ m_it -= n; return *this; }
reference operator[](difference_type n) const
{
#if defined(BOOST_HAS_RVALUE_REFS)
return m_it[n];
#else
return boost::interprocess::move(m_it[n]);
#endif
}
friend bool operator==(const move_iterator& x, const move_iterator& y)
{ return x.base() == y.base(); }
friend bool operator!=(const move_iterator& x, const move_iterator& y)
{ return x.base() != y.base(); }
friend bool operator< (const move_iterator& x, const move_iterator& y)
{ return x.base() < y.base(); }
friend bool operator<=(const move_iterator& x, const move_iterator& y)
{ return x.base() <= y.base(); }
friend bool operator> (const move_iterator& x, const move_iterator& y)
{ return x.base() > y.base(); }
friend bool operator>=(const move_iterator& x, const move_iterator& y)
{ return x.base() >= y.base(); }
friend difference_type operator-(const move_iterator& x, const move_iterator& y)
{ return x.base() - y.base(); }
friend move_iterator operator+(difference_type n, const move_iterator& x)
{ return move_iterator(x.base() + n); }
private:
It m_it;
};
//is_move_iterator
namespace move_detail {
template <class I>
struct is_move_iterator
{
static const bool value = false;
};
template <class I>
struct is_move_iterator< ::boost::interprocess::move_iterator<I> >
{
static const bool value = true;
};
} //namespace move_detail {
//////////////////////////////////////////////////////////////////////////////
//
// move_iterator
//
//////////////////////////////////////////////////////////////////////////////
//!
//! <b>Returns</b>: move_iterator<It>(i).
template<class It>
move_iterator<It> make_move_iterator(const It &it)
{ return move_iterator<It>(it); }
//////////////////////////////////////////////////////////////////////////////
//
// back_move_insert_iterator
//
//////////////////////////////////////////////////////////////////////////////
//! A move insert iterator that move constructs elements at the
//! back of a container
template <typename C> // C models Container
class back_move_insert_iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
C* container_m;
public:
typedef C container_type;
explicit back_move_insert_iterator(C& x) : container_m(&x) { }
back_move_insert_iterator& operator=(typename C::reference x)
{ container_m->push_back(boost::interprocess::move(x)); return *this; }
back_move_insert_iterator& operator*() { return *this; }
back_move_insert_iterator& operator++() { return *this; }
back_move_insert_iterator& operator++(int) { return *this; }
};
//!
//! <b>Returns</b>: back_move_insert_iterator<C>(x).
template <typename C> // C models Container
inline back_move_insert_iterator<C> back_move_inserter(C& x)
{
return back_move_insert_iterator<C>(x);
}
//////////////////////////////////////////////////////////////////////////////
//
// front_move_insert_iterator
//
//////////////////////////////////////////////////////////////////////////////
//! A move insert iterator that move constructs elements int the
//! front of a container
template <typename C> // C models Container
class front_move_insert_iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
C* container_m;
public:
typedef C container_type;
explicit front_move_insert_iterator(C& x) : container_m(&x) { }
front_move_insert_iterator& operator=(typename C::reference x)
{ container_m->push_front(boost::interprocess::move(x)); return *this; }
front_move_insert_iterator& operator*() { return *this; }
front_move_insert_iterator& operator++() { return *this; }
front_move_insert_iterator& operator++(int) { return *this; }
};
//!
//! <b>Returns</b>: front_move_insert_iterator<C>(x).
template <typename C> // C models Container
inline front_move_insert_iterator<C> front_move_inserter(C& x)
{
return front_move_insert_iterator<C>(x);
}
//////////////////////////////////////////////////////////////////////////////
//
// insert_move_iterator
//
//////////////////////////////////////////////////////////////////////////////
template <typename C> // C models Container
class move_insert_iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
C* container_m;
typename C::iterator pos_;
public:
typedef C container_type;
explicit move_insert_iterator(C& x, typename C::iterator pos)
: container_m(&x), pos_(pos)
{}
move_insert_iterator& operator=(typename C::reference x)
{
pos_ = container_m->insert(pos_, boost::interprocess::move(x));
++pos_;
return *this;
}
move_insert_iterator& operator*() { return *this; }
move_insert_iterator& operator++() { return *this; }
move_insert_iterator& operator++(int) { return *this; }
};
//!
//! <b>Returns</b>: move_insert_iterator<C>(x, it).
template <typename C> // C models Container
inline move_insert_iterator<C> move_inserter(C& x, typename C::iterator it)
{
return move_insert_iterator<C>(x, it);
}
//////////////////////////////////////////////////////////////////////////////
//
// move
//
//////////////////////////////////////////////////////////////////////////////
//! <b>Effects</b>: Moves elements in the range [first,last) into the range [result,result + (last -
//! first)) starting from first and proceeding to last. For each non-negative integer n < (last-first),
//! performs *(result + n) = boost::interprocess::move (*(first + n)).
//!
//! <b>Effects</b>: result + (last - first).
//!
//! <b>Requires</b>: result shall not be in the range [first,last).
//!
//! <b>Complexity</b>: Exactly last - first move assignments.
template <typename I, // I models InputIterator
typename O> // O models OutputIterator
O move(I f, I l, O result)
{
while (f != l) {
*result = boost::interprocess::move(*f);
++f; ++result;
}
return result;
}
//////////////////////////////////////////////////////////////////////////////
//
// move_backward
//
//////////////////////////////////////////////////////////////////////////////
//! <b>Effects</b>: Moves elements in the range [first,last) into the range
//! [result - (last-first),result) starting from last - 1 and proceeding to
//! first. For each positive integer n <= (last - first),
//! performs *(result - n) = boost::interprocess::move(*(last - n)).
//!
//! <b>Requires</b>: result shall not be in the range [first,last).
//!
//! <b>Returns</b>: result - (last - first).
//!
//! <b>Complexity</b>: Exactly last - first assignments.
template <typename I, // I models BidirectionalIterator
typename O> // O models BidirectionalIterator
O move_backward(I f, I l, O result)
{
while (f != l) {
--l; --result;
*result = boost::interprocess::move(*l);
}
return result;
}
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_move
//
//////////////////////////////////////////////////////////////////////////////
//! <b>Effects</b>:
//! \code
//! for (; first != last; ++result, ++first)
//! new (static_cast<void*>(&*result))
//! typename iterator_traits<ForwardIterator>::value_type(boost::interprocess::move(*first));
//! \endcode
//!
//! <b>Returns</b>: result
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
F uninitialized_move(I f, I l, F r
/// @cond
,typename enable_if<is_movable<typename std::iterator_traits<I>::value_type> >::type* = 0
/// @endcond
)
{
typedef typename std::iterator_traits<I>::value_type input_value_type;
while (f != l) {
::new(static_cast<void*>(&*r)) input_value_type(boost::interprocess::move(*f));
++f; ++r;
}
return r;
}
/// @cond
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
F uninitialized_move(I f, I l, F r,
typename disable_if<is_movable<typename std::iterator_traits<I>::value_type> >::type* = 0)
{
return std::uninitialized_copy(f, l, r);
}
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_or_move
//
//////////////////////////////////////////////////////////////////////////////
namespace move_detail {
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
F uninitialized_move_move_iterator(I f, I l, F r,
typename enable_if< is_movable<typename I::value_type> >::type* = 0)
{
return boost::interprocess::uninitialized_move(f, l, r);
}
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
F uninitialized_move_move_iterator(I f, I l, F r,
typename disable_if< is_movable<typename I::value_type> >::type* = 0)
{
return std::uninitialized_copy(f.base(), l.base(), r);
}
} //namespace move_detail {
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
F uninitialized_copy_or_move(I f, I l, F r,
typename enable_if< move_detail::is_move_iterator<I> >::type* = 0)
{
return boost::interprocess::move_detail::uninitialized_move_move_iterator(f, l, r);
}
/// @endcond
//! <b>Effects</b>:
//! \code
//! for (; first != last; ++result, ++first)
//! new (static_cast<void*>(&*result))
//! typename iterator_traits<ForwardIterator>::value_type(*first);
//! \endcode
//!
//! <b>Returns</b>: result
//!
//! <b>Note</b>: This function is provided because
//! <i>std::uninitialized_copy</i> from some STL implementations
//! is not compatible with <i>move_iterator</i>
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
F uninitialized_copy_or_move(I f, I l, F r
/// @cond
,typename disable_if< move_detail::is_move_iterator<I> >::type* = 0
/// @endcond
)
{
return std::uninitialized_copy(f, l, r);
}
///has_trivial_destructor_after_move<> == true_type
///specialization for optimizations
template <class T>
struct has_trivial_destructor_after_move
: public boost::has_trivial_destructor<T>
{};
} //namespace interprocess {
} //namespace boost {
#endif //#ifndef BOOST_INTERPROCESS_MOVE_HPP

View File

@@ -1,138 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_MOVE_ITERATOR_HPP_INCLUDED
#define BOOST_INTERPROCESS_MOVE_ITERATOR_HPP_INCLUDED
#include <iterator>
#include <boost/interprocess/detail/move.hpp>
namespace boost{
namespace interprocess{
namespace detail{
template <class It>
class move_iterator
{
public:
typedef It iterator_type;
typedef typename std::iterator_traits<iterator_type>::value_type value_type;
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
typedef typename move_type<value_type>::type reference;
#else
typedef value_type && reference;
#endif
typedef typename std::iterator_traits<iterator_type>::pointer pointer;
typedef typename std::iterator_traits<iterator_type>::difference_type difference_type;
typedef typename std::iterator_traits<iterator_type>::iterator_category iterator_category;
move_iterator()
{}
explicit move_iterator(It i)
: m_it(i)
{}
template <class U>
move_iterator(const move_iterator<U>& u)
: m_it(u.base())
{}
const iterator_type &base() const
{ return m_it; }
iterator_type &base()
{ return m_it; }
reference operator*() const
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
{ return detail::move_impl(*m_it); }
#else
{ return *m_it; }
#endif
pointer operator->() const
{ return m_it; }
move_iterator& operator++()
{ ++m_it; return *this; }
move_iterator<iterator_type> operator++(int)
{ move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; }
move_iterator& operator--()
{ --m_it; return *this; }
move_iterator<iterator_type> operator--(int)
{ move_iterator<iterator_type> tmp(*this); --(*this); return tmp; }
move_iterator<iterator_type> operator+ (difference_type n) const
{ return move_iterator<iterator_type>(m_it + n); }
move_iterator& operator+=(difference_type n)
{ m_it += n; return *this; }
move_iterator<iterator_type> operator- (difference_type n) const
{ return move_iterator<iterator_type>(m_it - n); }
move_iterator& operator-=(difference_type n)
{ m_it -= n; return *this; }
reference operator[](difference_type n) const
{ return detail::move_impl(m_it[n]); }
private:
It m_it;
};
template <class It> inline
bool operator==(const move_iterator<It>& x, const move_iterator<It>& y)
{ return x.base() == y.base(); }
template <class It> inline
bool operator!=(const move_iterator<It>& x, const move_iterator<It>& y)
{ return x.base() != y.base(); }
template <class It> inline
bool operator< (const move_iterator<It>& x, const move_iterator<It>& y)
{ return x.base() < y.base(); }
template <class It> inline
bool operator<=(const move_iterator<It>& x, const move_iterator<It>& y)
{ return x.base() <= y.base(); }
template <class It> inline
bool operator> (const move_iterator<It>& x, const move_iterator<It>& y)
{ return x.base() > y.base(); }
template <class It> inline
bool operator>=(const move_iterator<It>& x, const move_iterator<It>& y)
{ return x.base() >= y.base(); }
template <class It> inline
typename move_iterator<It>::difference_type
operator-(const move_iterator<It>& x, const move_iterator<It>& y)
{ return x.base() - y.base(); }
template <class It> inline
move_iterator<It>
operator+(typename move_iterator<It>::difference_type n
,const move_iterator<It>& x)
{ return move_iterator<It>(x.base() + n); }
template<class It>
move_iterator<It> make_move_iterator(const It &it)
{ return move_iterator<It>(it); }
} //namespace detail{
} //namespace interprocess{
} //namespace boost{
#endif //#ifndef BOOST_INTERPROCESS_MOVE_ITERATOR_HPP_INCLUDED

View File

@@ -59,6 +59,9 @@ struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <class Cond, class T = void>
struct disable_if : public enable_if_c<!Cond::value, T> {};
template <class T, class U>
class is_convertible
{
@@ -105,7 +108,8 @@ template <class Pair>
struct select1st
// : public std::unary_function<Pair, typename Pair::first_type>
{
const typename Pair::first_type& operator()(const Pair& x) const
template<class OtherPair>
const typename Pair::first_type& operator()(const OtherPair& x) const
{ return x.first; }
const typename Pair::first_type& operator()(const typename Pair::first_type& x) const

View File

@@ -72,11 +72,11 @@ struct CtorNArg : public placement_destroy<T>
private:
template<int ...IdxPack>
void construct(void *mem, detail::true_, const index_tuple<IdxPack...>&)
{ new((void*)mem)T(*detail::forward_impl<Args>(get<IdxPack>(args_))...); }
{ new((void*)mem)T(*boost::interprocess::forward<Args>(get<IdxPack>(args_))...); }
template<int ...IdxPack>
void construct(void *mem, detail::false_, const index_tuple<IdxPack...>&)
{ new((void*)mem)T(detail::forward_impl<Args>(get<IdxPack>(args_))...); }
{ new((void*)mem)T(boost::interprocess::forward<Args>(get<IdxPack>(args_))...); }
template<int ...IdxPack>
void do_increment(detail::true_, const index_tuple<IdxPack...>&)
@@ -120,7 +120,7 @@ class named_proxy
template<class ...Args>
T *operator()(Args &&...args) const
{
CtorNArg<T, is_iterator, Args...> ctor_obj(detail::forward_impl<Args>(args)...);
CtorNArg<T, is_iterator, Args...> ctor_obj(boost::interprocess::forward<Args>(args)...);
return mp_mngr->template
generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
}
@@ -211,7 +211,7 @@ struct Ctor0Arg : public placement_destroy<T>
//be able to bind temporaries. After that we will un-const them.
//This cast is ugly but it is necessary until "perfect forwarding"
//is achieved in C++0x. Meanwhile, if we want to be able to
//bind rvalues with non-const references, we have to be ugly
//bind lvalues with non-const references, we have to be ugly
#define BOOST_PP_LOCAL_MACRO(n) \
template<class T, bool is_iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \
struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \

View File

@@ -13,9 +13,9 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
//#include <boost/interprocess/detail/utilities.hpp>
#include <string>
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
@@ -35,11 +35,11 @@
namespace boost {
namespace interprocess {
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
typedef void * file_handle_t;
typedef long long offset_t;
typedef struct{
typedef struct mapping_handle_impl_t{
void * handle;
bool is_shm;
} mapping_handle_t;
@@ -65,6 +65,14 @@ inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
return ret;
}
inline mapping_handle_t mapping_handle_from_shm_handle(file_handle_t hnd)
{
mapping_handle_t ret;
ret.handle = hnd;
ret.is_shm = true;
return ret;
}
inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
{ return hnd.handle; }
@@ -99,10 +107,7 @@ inline file_handle_t open_existing_file
}
inline bool delete_file(const char *name)
{ return winapi::delete_file(name); }
inline bool delete_file_on_reboot_if_possible(const char *filename)
{ return winapi::move_file_ex(filename, 0, winapi::movefile_delay_until_reboot); }
{ return winapi::unlink_file(name); }
inline bool truncate_file (file_handle_t hnd, std::size_t size)
{
@@ -191,16 +196,89 @@ inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
return (acquired = true);
}
inline bool release_file_lock_sharable(file_handle_t hnd)
{ return release_file_lock(hnd); }
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
inline bool delete_subdirectories_recursive
(const std::string &refcstrRootDirectory, const char *dont_delete_this, unsigned int count)
{
bool bSubdirectory = false; // Flag, indicating whether
// subdirectories have been found
void * hFile; // Handle to directory
std::string strFilePath; // Filepath
std::string strPattern; // Pattern
winapi::win32_find_data_t FileInformation; // File information
//Find all files and directories
strPattern = refcstrRootDirectory + "\\*.*";
hFile = winapi::find_first_file(strPattern.c_str(), &FileInformation);
if(hFile != winapi::invalid_handle_value){
do{
//If it's not "." or ".." or the pointed root_level dont_delete_this erase it
if(FileInformation.cFileName[0] != '.' &&
!(dont_delete_this && count == 0 && std::strcmp(dont_delete_this, FileInformation.cFileName) == 0)){
strFilePath.erase();
strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;
//If it's a directory, go recursive
if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){
// Delete subdirectory
if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1))
return false;
}
//If it's a file, just delete it
else{
// Set file attributes
//if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0)
//return winapi::get_last_error();
// Delete file
if(winapi::delete_file(strFilePath.c_str()) == 0)
return false;
}
}
//Go to the next file
} while(winapi::find_next_file(hFile, &FileInformation) == 1);
// Close handle
winapi::find_close(hFile);
//See if the loop has ended with an error or just because we've traversed all the files
if(winapi::get_last_error() != winapi::error_no_more_files){
return false;
}
else
{
//Erase empty subdirectories or original refcstrRootDirectory
if(!bSubdirectory && count)
{
// Set directory attributes
//if(::SetFileAttributes(refcstrRootDirectory.c_str(), FILE_ATTRIBUTE_NORMAL) == 0)
//return ::GetLastError();
// Delete directory
if(winapi::remove_directory(refcstrRootDirectory.c_str()) == 0)
return false;
}
}
}
return true;
}
//This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
{
return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u);
}
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
typedef int file_handle_t;
typedef off_t offset_t;
typedef file_handle_t mapping_handle_t;
typedef struct mapping_handle_impl_t
{
file_handle_t handle;
bool is_xsi;
} mapping_handle_t;
typedef enum { read_only = O_RDONLY
, read_write = O_RDWR
@@ -216,10 +294,15 @@ typedef enum { file_begin = SEEK_SET
namespace detail{
inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
{ return hnd; }
{
mapping_handle_t ret;
ret.handle = hnd;
ret.is_xsi = false;
return ret;
}
inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
{ return hnd; }
{ return hnd.handle; }
inline bool create_directory(const char *path)
{ return ::mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0; }
@@ -263,12 +346,6 @@ inline file_handle_t open_existing_file
inline bool delete_file(const char *name)
{ return ::unlink(name) == 0; }
inline bool delete_file_on_reboot_if_possible(const char *)
{ //Function not implemented in POSIX functions
return false;
}
inline bool truncate_file (file_handle_t hnd, std::size_t size)
{ return 0 == ::ftruncate(hnd, size); }
@@ -365,7 +442,7 @@ inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
inline bool release_file_lock_sharable(file_handle_t hnd)
{ return release_file_lock(hnd); }
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
} //namespace detail{
} //namespace interprocess {

View File

@@ -14,7 +14,7 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
@@ -30,7 +30,7 @@ namespace boost {
namespace interprocess {
namespace detail{
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
typedef unsigned long OS_process_id_t;
typedef unsigned long OS_thread_id_t;
@@ -40,6 +40,9 @@ typedef OS_thread_id_t OS_systemwide_thread_id_t;
inline OS_process_id_t get_current_process_id()
{ return winapi::get_current_process_id(); }
inline OS_process_id_t get_invalid_process_id()
{ return OS_process_id_t(0); }
//thread
inline OS_thread_id_t get_current_thread_id()
{ return winapi::get_current_thread_id(); }
@@ -59,6 +62,12 @@ inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
return get_current_thread_id();
}
inline void systemwide_thread_id_copy
(const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
{
to = from;
}
inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
{
return equal_thread_id(id1, id2);
@@ -69,24 +78,56 @@ inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
return get_invalid_thread_id();
}
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
typedef pthread_t OS_thread_id_t;
typedef pid_t OS_process_id_t;
struct OS_systemwide_thread_id_t
{
OS_systemwide_thread_id_t()
: pid(), tid()
{}
OS_systemwide_thread_id_t(pid_t p, pthread_t t)
: pid(p), tid(t)
{}
OS_systemwide_thread_id_t(const OS_systemwide_thread_id_t &x)
: pid(x.pid), tid(x.tid)
{}
OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x)
: pid(x.pid), tid(x.tid)
{}
OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x)
{ pid = x.pid; tid = x.tid; return *this; }
OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x)
{ pid = x.pid; tid = x.tid; return *this; }
void operator=(const OS_systemwide_thread_id_t &x) volatile
{ pid = x.pid; tid = x.tid; }
pid_t pid;
pthread_t tid;
};
inline void systemwide_thread_id_copy
(const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
{
to.pid = from.pid;
to.tid = from.tid;
}
//process
inline OS_process_id_t get_current_process_id()
{ return ::getpid(); }
inline OS_process_id_t get_invalid_process_id()
{ return pid_t(0); }
//thread
inline OS_thread_id_t get_current_thread_id()
{ return ::pthread_self(); }
@@ -116,10 +157,10 @@ inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, con
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
{
return OS_systemwide_thread_id_t(pid_t(0), get_invalid_thread_id());
return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
}
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
} //namespace detail{
} //namespace interprocess {

View File

@@ -36,7 +36,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
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
//!
@@ -46,7 +46,7 @@
//!
#endif
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_INTERPROCESS_PARAM(U, u) \
U && u \
//!
@@ -56,7 +56,7 @@
//!
#endif
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
//!
@@ -70,7 +70,7 @@
BOOST_PP_CAT(++m_p, n) \
//!
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \
//!
@@ -80,25 +80,13 @@
//!
#endif
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
#define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \
detail::forward_impl< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
//!
#else
#define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \
BOOST_PP_CAT(p, n) \
//!
#endif
#define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \
boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
//!
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
detail::forward_impl< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
//!
#else
#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
BOOST_PP_CAT(m_p, n) \
//!
#endif
#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
//!
#define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \
BOOST_PP_CAT(*m_p, n) \

View File

@@ -18,6 +18,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/utilities.hpp>
@@ -27,6 +29,8 @@
#include <string> //char_traits
#include <new> //std::nothrow
#include <utility> //std::pair
#include <cassert> //assert
#include <functional> //unary_function
#ifndef BOOST_NO_EXCEPTIONS
#include <exception>
#endif
@@ -75,7 +79,7 @@ struct block_header
block_header(std::size_t value_bytes
,std::size_t value_alignment
,std::size_t allocation_type
,std::size_t alloc_type
,std::size_t sizeof_char
,std::size_t num_char
)
@@ -83,7 +87,7 @@ struct block_header
, m_num_char(num_char)
, m_value_alignment(value_alignment)
, m_alloc_type_sizeof_char
( ((unsigned char)allocation_type << 5u) |
( ((unsigned char)alloc_type << 5u) |
((unsigned char)sizeof_char & 0x1F) )
{};
@@ -94,7 +98,7 @@ struct block_header
std::size_t total_size() const
{
if(allocation_type() != anonymous_type){
if(alloc_type() != anonymous_type){
return name_offset() + (m_num_char+1)*sizeof_char();
}
else{
@@ -114,7 +118,7 @@ struct block_header
+ total_size();
}
std::size_t allocation_type() const
std::size_t alloc_type() const
{ return (m_alloc_type_sizeof_char >> 5u)&(unsigned char)0x7; }
std::size_t sizeof_char() const
@@ -252,6 +256,7 @@ struct char_if_void<void>
typedef instance_t<anonymous_type> anonymous_instance_t;
typedef instance_t<unique_type> unique_instance_t;
template<class Hook, class CharType>
struct intrusive_value_type_impl
: public Hook
@@ -325,7 +330,7 @@ class char_ptr_holder
template<class CharT, class VoidPointer>
struct index_key
{
typedef typename detail::
typedef typename boost::
pointer_to_other<VoidPointer, const CharT>::type const_char_ptr_t;
typedef CharT char_type;
@@ -471,6 +476,26 @@ struct segment_manager_iterator_transform
} //namespace detail {
//These pointers are the ones the user will use to
//indicate previous allocation types
static const detail::anonymous_instance_t * anonymous_instance = 0;
static const detail::unique_instance_t * unique_instance = 0;
namespace detail_really_deep_namespace {
//Otherwise, gcc issues a warning of previously defined
//anonymous_instance and unique_instance
struct dummy
{
dummy()
{
(void)anonymous_instance;
(void)unique_instance;
}
};
} //detail_really_deep_namespace
}} //namespace boost { namespace interprocess
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -18,10 +18,87 @@
#include <boost/interprocess/exceptions.hpp>
#include <string>
#if (defined BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
#endif
namespace boost {
namespace interprocess {
namespace detail {
#if (defined BOOST_INTERPROCESS_WINDOWS)
inline void tmp_filename(const char *filename, std::string &tmp_name)
{
const char *tmp_dir = get_temporary_path();
if(!tmp_dir){
error_info err = system_error_code();
throw interprocess_exception(err);
}
tmp_name = tmp_dir;
//Remove final null.
tmp_name += "/boost_interprocess/";
char bootstamp[winapi::BootstampLength*2+1];
std::size_t bootstamp_length = winapi::BootstampLength*2;
winapi::get_boot_time_str(bootstamp, bootstamp_length);
bootstamp[winapi::BootstampLength*2] = 0;
tmp_name += bootstamp;
tmp_name += '/';
tmp_name += filename;
}
inline void create_tmp_dir_and_get_filename(const char *filename, std::string &tmp_name)
{
//First get the temp directory
const char *tmp_path = get_temporary_path();
if(!tmp_path){
error_info err = system_error_code();
throw interprocess_exception(err);
}
//Create Boost.Interprocess dir
tmp_name = tmp_path;
tmp_name += "/boost_interprocess";
//If fails, check that it's because already exists
if(!create_directory(tmp_name.c_str())){
error_info info(system_error_code());
if(info.get_error_code() != already_exists_error){
throw interprocess_exception(info);
}
}
//Obtain bootstamp string
char bootstamp[winapi::BootstampLength*2+1];
std::size_t bootstamp_length = winapi::BootstampLength*2;
winapi::get_boot_time_str(bootstamp, bootstamp_length);
bootstamp[winapi::BootstampLength*2] = 0;
//Create a new subdirectory with the bootstamp
std::string root_tmp_name = tmp_name;
tmp_name += '/';
tmp_name += bootstamp;
//If fails, check that it's because already exists
if(!create_directory(tmp_name.c_str())){
error_info info(system_error_code());
if(info.get_error_code() != already_exists_error){
throw interprocess_exception(info);
}
}
//Now erase all old directories created in the previous boot sessions
delete_subdirectories(root_tmp_name, bootstamp);
//Add filename
tmp_name += '/';
tmp_name += filename;
}
#else //POSIX SYSTEMS
inline void tmp_filename(const char *filename, std::string &tmp_name)
{
const char *tmp_dir = get_temporary_path();
@@ -61,6 +138,8 @@ inline void create_tmp_dir_and_get_filename(const char *filename, std::string &t
tmp_name += filename;
}
#endif
inline void add_leading_slash(const char *name, std::string &new_name)
{
if(name[0] != '/'){

View File

@@ -0,0 +1,180 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
#define BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <iterator>
#include <boost/interprocess/detail/type_traits.hpp>
namespace boost {
namespace interprocess {
template <class PseudoReference>
struct operator_arrow_proxy
{
operator_arrow_proxy(const PseudoReference &px)
: m_value(px)
{}
PseudoReference* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
mutable PseudoReference m_value;
};
template <class T>
struct operator_arrow_proxy<T&>
{
operator_arrow_proxy(T &px)
: m_value(px)
{}
T* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
mutable T &m_value;
};
template <class Iterator, class UnaryFunction>
class transform_iterator
: public UnaryFunction
, public std::iterator
< typename Iterator::iterator_category
, typename detail::remove_reference<typename UnaryFunction::result_type>::type
, typename Iterator::difference_type
, operator_arrow_proxy<typename UnaryFunction::result_type>
, typename UnaryFunction::result_type>
{
public:
explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
: UnaryFunction(f), m_it(it)
{}
explicit transform_iterator()
: UnaryFunction(), m_it()
{}
//Constructors
transform_iterator& operator++()
{ increment(); return *this; }
transform_iterator operator++(int)
{
transform_iterator result (*this);
increment();
return result;
}
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
{ return i.equal(i2); }
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i == i2); }
/*
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
{ return i2 < i; }
friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i > i2); }
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i < i2); }
*/
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
transform_iterator& operator+=(typename Iterator::difference_type off)
{ this->advance(off); return *this; }
transform_iterator operator+(typename Iterator::difference_type off) const
{
transform_iterator other(*this);
other.advance(off);
return other;
}
friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
{ return right + off; }
transform_iterator& operator-=(typename Iterator::difference_type off)
{ this->advance(-off); return *this; }
transform_iterator operator-(typename Iterator::difference_type off) const
{ return *this + (-off); }
typename UnaryFunction::result_type operator*() const
{ return dereference(); }
operator_arrow_proxy<typename UnaryFunction::result_type>
operator->() const
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
Iterator & base()
{ return m_it; }
const Iterator & base() const
{ return m_it; }
private:
Iterator m_it;
void increment()
{ ++m_it; }
void decrement()
{ --m_it; }
bool equal(const transform_iterator &other) const
{ return m_it == other.m_it; }
bool less(const transform_iterator &other) const
{ return other.m_it < m_it; }
typename UnaryFunction::result_type dereference() const
{ return UnaryFunction::operator()(*m_it); }
void advance(typename Iterator::difference_type n)
{ std::advance(m_it, n); }
typename Iterator::difference_type distance_to(const transform_iterator &other)const
{ return std::distance(other.m_it, m_it); }
};
template <class Iterator, class UnaryFunc>
transform_iterator<Iterator, UnaryFunc>
make_transform_iterator(Iterator it, UnaryFunc fun)
{
return transform_iterator<Iterator, UnaryFunc>(it, fun);
}
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP

View File

@@ -120,13 +120,13 @@ struct add_reference<T&>
template<>
struct add_reference<void>
{
typedef nat& type;
typedef nat &type;
};
template<>
struct add_reference<const void>
{
typedef const nat& type;
typedef const nat &type;
};
template <class T>

View File

@@ -26,11 +26,10 @@
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/interprocess/detail/min_max.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/iterators.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
#include <boost/interprocess/detail/preprocessor.hpp>
#endif
#include <boost/interprocess/detail/transform_iterator.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/containers/version_type.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <utility>
#include <algorithm>
@@ -70,321 +69,6 @@ inline void do_swap(T& x, T& y)
swap(x, y);
}
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an object using a STL allocator.
template <class Allocator>
struct scoped_ptr_dealloc_functor
{
typedef typename Allocator::pointer pointer;
typedef detail::integral_constant<unsigned,
boost::interprocess::detail::
version<Allocator>::value> alloc_version;
typedef detail::integral_constant<unsigned, 1> allocator_v1;
typedef detail::integral_constant<unsigned, 2> allocator_v2;
private:
void priv_deallocate(const typename Allocator::pointer &p, allocator_v1)
{ m_alloc.deallocate(p, 1); }
void priv_deallocate(const typename Allocator::pointer &p, allocator_v2)
{ m_alloc.deallocate_one(p); }
public:
Allocator& m_alloc;
scoped_ptr_dealloc_functor(Allocator& a)
: m_alloc(a) {}
void operator()(pointer ptr)
{ if (ptr) priv_deallocate(ptr, alloc_version()); }
};
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an object using a STL allocator.
template <class Allocator>
struct scoped_deallocator
{
typedef typename Allocator::pointer pointer;
typedef detail::integral_constant<unsigned,
boost::interprocess::detail::
version<Allocator>::value> alloc_version;
typedef detail::integral_constant<unsigned, 1> allocator_v1;
typedef detail::integral_constant<unsigned, 2> allocator_v2;
private:
void priv_deallocate(allocator_v1)
{ m_alloc.deallocate(m_ptr, 1); }
void priv_deallocate(allocator_v2)
{ m_alloc.deallocate_one(m_ptr); }
scoped_deallocator(const scoped_deallocator &);
scoped_deallocator& operator=(const scoped_deallocator &);
public:
pointer m_ptr;
Allocator& m_alloc;
scoped_deallocator(pointer p, Allocator& a)
: m_ptr(p), m_alloc(a) {}
~scoped_deallocator()
{ if (m_ptr)priv_deallocate(alloc_version()); }
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
scoped_deallocator(scoped_deallocator &&o)
: m_ptr(o.m_ptr), m_alloc(o.m_alloc)
{
#else
scoped_deallocator(moved_object<scoped_deallocator> mo)
: m_ptr(mo.get().m_ptr), m_alloc(mo.get().m_alloc)
{
scoped_deallocator &o = mo.get();
#endif
o.release();
}
pointer get() const
{ return m_ptr; }
void release()
{ m_ptr = 0; }
};
} //namespace detail {
template <class Allocator>
struct is_movable<boost::interprocess::detail::scoped_deallocator<Allocator> >
{
static const bool value = true;
};
namespace detail {
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an array of objects using a STL allocator.
template <class Allocator>
struct scoped_array_deallocator
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::size_type size_type;
scoped_array_deallocator(pointer p, Allocator& a, size_type length)
: m_ptr(p), m_alloc(a), m_length(length) {}
~scoped_array_deallocator()
{ if (m_ptr) m_alloc.deallocate(m_ptr, m_length); }
void release()
{ m_ptr = 0; }
private:
pointer m_ptr;
Allocator& m_alloc;
size_type m_length;
};
template <class Allocator>
struct null_scoped_array_deallocator
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::size_type size_type;
null_scoped_array_deallocator(pointer, Allocator&, size_type)
{}
void release()
{}
};
//!A deleter for scoped_ptr that destroys
//!an object using a STL allocator.
template <class Allocator>
struct scoped_destructor_n
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::value_type value_type;
typedef typename Allocator::size_type size_type;
pointer m_p;
size_type m_n;
scoped_destructor_n(pointer p, size_type n)
: m_p(p), m_n(n)
{}
void release()
{ m_p = 0; }
void increment_size(size_type inc)
{ m_n += inc; }
~scoped_destructor_n()
{
if(!m_p) return;
value_type *raw_ptr = detail::get_pointer(m_p);
for(std::size_t i = 0; i < m_n; ++i, ++raw_ptr)
raw_ptr->~value_type();
}
};
//!A deleter for scoped_ptr that destroys
//!an object using a STL allocator.
template <class Allocator>
struct null_scoped_destructor_n
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::size_type size_type;
null_scoped_destructor_n(pointer, size_type)
{}
void increment_size(size_type)
{}
void release()
{}
};
template <class A>
class allocator_destroyer
{
typedef typename A::value_type value_type;
typedef detail::integral_constant<unsigned,
boost::interprocess::detail::
version<A>::value> alloc_version;
typedef detail::integral_constant<unsigned, 1> allocator_v1;
typedef detail::integral_constant<unsigned, 2> allocator_v2;
private:
A & a_;
private:
void priv_deallocate(const typename A::pointer &p, allocator_v1)
{ a_.deallocate(p, 1); }
void priv_deallocate(const typename A::pointer &p, allocator_v2)
{ a_.deallocate_one(p); }
public:
allocator_destroyer(A &a)
: a_(a)
{}
void operator()(const typename A::pointer &p)
{
detail::get_pointer(p)->~value_type();
priv_deallocate(p, alloc_version());
}
};
template <class A>
class allocator_destroyer_and_chain_builder
{
typedef typename A::value_type value_type;
typedef typename A::multiallocation_iterator multiallocation_iterator;
typedef typename A::multiallocation_chain multiallocation_chain;
A & a_;
multiallocation_chain &c_;
public:
allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
: a_(a), c_(c)
{}
void operator()(const typename A::pointer &p)
{
value_type *vp = detail::get_pointer(p);
vp->~value_type();
c_.push_back(vp);
}
};
template <class A>
class allocator_multialloc_chain_node_deallocator
{
typedef typename A::value_type value_type;
typedef typename A::multiallocation_iterator multiallocation_iterator;
typedef typename A::multiallocation_chain multiallocation_chain;
typedef allocator_destroyer_and_chain_builder<A> chain_builder;
A & a_;
multiallocation_chain c_;
public:
allocator_multialloc_chain_node_deallocator(A &a)
: a_(a), c_()
{}
chain_builder get_chain_builder()
{ return chain_builder(a_, c_); }
~allocator_multialloc_chain_node_deallocator()
{
multiallocation_iterator it(c_.get_it());
if(it != multiallocation_iterator())
a_.deallocate_individual(it);
}
};
template <class A>
class allocator_multialloc_chain_array_deallocator
{
typedef typename A::value_type value_type;
typedef typename A::multiallocation_iterator multiallocation_iterator;
typedef typename A::multiallocation_chain multiallocation_chain;
typedef allocator_destroyer_and_chain_builder<A> chain_builder;
A & a_;
multiallocation_chain c_;
public:
allocator_multialloc_chain_array_deallocator(A &a)
: a_(a), c_()
{}
chain_builder get_chain_builder()
{ return chain_builder(a_, c_); }
~allocator_multialloc_chain_array_deallocator()
{
multiallocation_iterator it(c_.get_it());
if(it != multiallocation_iterator())
a_.deallocate_many(it);
}
};
//!A class used for exception-safe multi-allocation + construction.
template <class Allocator>
struct multiallocation_destroy_dealloc
{
typedef typename Allocator::multiallocation_iterator multiallocation_iterator;
typedef typename Allocator::value_type value_type;
multiallocation_iterator m_itbeg;
Allocator& m_alloc;
multiallocation_destroy_dealloc(multiallocation_iterator itbeg, Allocator& a)
: m_itbeg(itbeg), m_alloc(a) {}
~multiallocation_destroy_dealloc()
{
multiallocation_iterator endit;
while(m_itbeg != endit){
detail::get_pointer(&*m_itbeg)->~value_type();
m_alloc.deallocate(&*m_itbeg, 1);
++m_itbeg;
}
}
void next()
{ ++m_itbeg; }
void release()
{ m_itbeg = multiallocation_iterator(); }
};
//Rounds "orig_size" by excess to round_to bytes
inline std::size_t get_rounded_size(std::size_t orig_size, std::size_t round_to)
{
@@ -415,18 +99,6 @@ struct ct_rounded_size
enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
};
template <std::size_t Value1, std::size_t Value2>
struct ct_min
{
enum { value = (Value1 < Value2)? Value1 : Value2 };
};
template <std::size_t Value1, std::size_t Value2>
struct ct_max
{
enum { value = (Value1 > Value2)? Value1 : Value2 };
};
// Gennaro Prota wrote this. Thanks!
template <int p, int n = 4>
struct ct_max_pow2_less
@@ -443,38 +115,6 @@ struct ct_max_pow2_less<0, 0>
static const std::size_t value = 0;
};
//!Obtains a generic pointer of the same type that
//!can point to other pointed type: Ptr<?> -> Ptr<NewValueType>
template<class T, class U>
struct pointer_to_other;
template<class T, class U,
template<class> class Sp>
struct pointer_to_other< Sp<T>, U >
{
typedef Sp<U> type;
};
template<class T, class T2, class U,
template<class, class> class Sp>
struct pointer_to_other< Sp<T, T2>, U >
{
typedef Sp<U, T2> type;
};
template<class T, class T2, class T3, class U,
template<class, class, class> class Sp>
struct pointer_to_other< Sp<T, T2, T3>, U >
{
typedef Sp<U, T2, T3> type;
};
template<class T, class U>
struct pointer_to_other< T*, U >
{
typedef U* type;
};
} //namespace detail {
//!Trait class to detect if an index is a node
@@ -486,7 +126,6 @@ struct is_node_index
enum { value = false };
};
//!Trait class to detect if an index is an intrusive
//!index. This will embed the derivation hook in each
//!allocation header, to provide memory for the intrusive
@@ -497,334 +136,6 @@ struct is_intrusive_index
enum { value = false };
};
template <class SizeType>
SizeType
get_next_capacity(const SizeType max_size
,const SizeType capacity
,const SizeType n)
{
// if (n > max_size - capacity)
// throw std::length_error("get_next_capacity");
const SizeType m3 = max_size/3;
if (capacity < m3)
return capacity + max_value(3*(capacity+1)/5, n);
if (capacity < m3*2)
return capacity + max_value((capacity+1)/2, n);
return max_size;
}
namespace detail {
template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
//std::pair compatibility
template <class D, class S>
pair(const std::pair<D, S>& p)
: first(p.first), second(p.second)
{}
//To resolve ambiguity with the variadic constructor of 1 argument
//and the previous constructor
pair(std::pair<T1, T2>& x)
: first(x.first), second(x.second)
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class D, class S>
pair(detail::moved_object<std::pair<D, S> > p)
: first(detail::move_impl(p.get().first)), second(detail::move_impl(p.get().second))
{}
#else
template <class D, class S>
pair(std::pair<D, S> && p)
: first(detail::move_impl(p.first)), second(detail::move_impl(p.second))
{}
#endif
pair()
: first(), second()
{}
pair(const pair<T1, T2>& x)
: first(x.first), second(x.second)
{}
//To resolve ambiguity with the variadic constructor of 1 argument
//and the copy constructor
pair(pair<T1, T2>& x)
: first(x.first), second(x.second)
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
pair(detail::moved_object<pair<T1, T2> > p)
: first(detail::move_impl(p.get().first)), second(detail::move_impl(p.get().second))
{}
#else
pair(pair<T1, T2> && p)
: first(detail::move_impl(p.first)), second(detail::move_impl(p.second))
{}
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class D, class S>
pair(detail::moved_object<pair<D, S> > p)
: first(detail::move_impl(p.get().first)), second(detail::move_impl(p.get().second))
{}
#else
template <class D, class S>
pair(pair<D, S> && p)
: first(detail::move_impl(p.first)), second(detail::move_impl(p.second))
{}
#endif
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
template<class U, class ...Args>
pair(U &&u, Args &&... args)
: first(detail::forward_impl<U>(u))
, second(detail::forward_impl<Args>(args)...)
{}
#else
template<class U>
pair(BOOST_INTERPROCESS_PARAM(U, u))
: first(detail::forward_impl<U>(u))
{}
#define BOOST_PP_LOCAL_MACRO(n) \
template<class U, BOOST_PP_ENUM_PARAMS(n, class P)> \
pair(BOOST_INTERPROCESS_PARAM(U, u) \
,BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
: first(detail::forward_impl<U>(u)) \
, second(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)) \
{} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
pair& operator=(detail::moved_object<pair<T1, T2> > p)
{
first = detail::move_impl(p.get().first);
second = detail::move_impl(p.get().second);
return *this;
}
#else
pair& operator=(pair<T1, T2> &&p)
{
first = detail::move_impl(p.first);
second = detail::move_impl(p.second);
return *this;
}
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
pair& operator=(detail::moved_object<std::pair<T1, T2> > p)
{
first = detail::move_impl(p.get().first);
second = detail::move_impl(p.get().second);
return *this;
}
#else
pair& operator=(std::pair<T1, T2> &&p)
{
first = detail::move_impl(p.first);
second = detail::move_impl(p.second);
return *this;
}
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class D, class S>
pair& operator=(detail::moved_object<std::pair<D, S> > p)
{
first = detail::move_impl(p.get().first);
second = detail::move_impl(p.get().second);
return *this;
}
#else
template <class D, class S>
pair& operator=(std::pair<D, S> &&p)
{
first = detail::move_impl(p.first);
second = detail::move_impl(p.second);
return *this;
}
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(detail::moved_object<pair> p)
{ std::swap(*this, p.get()); }
void swap(pair& p)
{ std::swap(*this, p); }
#else
void swap(pair &&p)
{ std::swap(*this, p); }
#endif
};
template <class T1, class T2>
inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(x.first == y.first && x.second == y.second); }
template <class T1, class T2>
inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(x.first < y.first ||
(!(y.first < x.first) && x.second < y.second)); }
template <class T1, class T2>
inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(x == y)); }
template <class T1, class T2>
inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return y < x; }
template <class T1, class T2>
inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(x < y)); }
template <class T1, class T2>
inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(y < x)); }
template <class T1, class T2>
inline pair<T1, T2> make_pair(T1 x, T2 y)
{ return pair<T1, T2>(x, y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class T1, class T2>
inline void swap(detail::moved_object<pair<T1, T2> > &x, pair<T1, T2> y)
{
swap(x.get().first, y.first);
swap(x.get().second, y.second);
}
template <class T1, class T2>
inline void swap(pair<T1, T2>& x, detail::moved_object<pair<T1, T2> > y)
{
swap(x.first, y.get().first);
swap(x.second, y.get().second);
}
template <class T1, class T2>
inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
{
swap(x.first, y.first);
swap(x.second, y.second);
}
#else
template <class T1, class T2>
inline void swap(pair<T1, T2>&&x, pair<T1, T2>&&y)
{
swap(x.first, y.first);
swap(x.second, y.second);
}
#endif
template<class T>
struct cast_functor
{
typedef typename detail::add_reference<T>::type result_type;
result_type operator()(char &ptr) const
{ return *static_cast<T*>(static_cast<void*>(&ptr)); }
};
template<class MultiallocChain, class T>
class multiallocation_chain_adaptor
{
private:
MultiallocChain chain_;
multiallocation_chain_adaptor
(const multiallocation_chain_adaptor &);
multiallocation_chain_adaptor &operator=
(const multiallocation_chain_adaptor &);
public:
typedef transform_iterator
< typename MultiallocChain::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
multiallocation_chain_adaptor()
: chain_()
{}
void push_back(T *mem)
{ chain_.push_back(mem); }
void push_front(T *mem)
{ chain_.push_front(mem); }
void swap(multiallocation_chain_adaptor &other_chain)
{ chain_.swap(other_chain.chain_); }
void splice_back(multiallocation_chain_adaptor &other_chain)
{ chain_.splice_back(other_chain.chain_); }
T *pop_front()
{ return static_cast<T*>(chain_.pop_front()); }
bool empty() const
{ return chain_.empty(); }
multiallocation_iterator get_it() const
{ return multiallocation_iterator(chain_.get_it()); }
std::size_t size() const
{ return chain_.size(); }
};
template<class T>
struct value_init
{
value_init()
: m_t()
{}
T m_t;
};
} //namespace detail {
//!The pair is movable if any of its members is movable
template <class T1, class T2>
struct is_movable<boost::interprocess::detail::pair<T1, T2> >
{
enum { value = is_movable<T1>::value || is_movable<T2>::value };
};
//!The pair is movable if any of its members is movable
template <class T1, class T2>
struct is_movable<std::pair<T1, T2> >
{
enum { value = is_movable<T1>::value || is_movable<T2>::value };
};
///has_trivial_destructor_after_move<> == true_type
///specialization for optimizations
template <class T>
struct has_trivial_destructor_after_move
: public boost::has_trivial_destructor<T>
{};
template <typename T> T*
addressof(T& v)
{
@@ -850,36 +161,6 @@ class value_eraser
bool m_erase;
};
template <class T>
struct sizeof_value
{
static const std::size_t value = sizeof(T);
};
template <>
struct sizeof_value<void>
{
static const std::size_t value = sizeof(void*);
};
template <>
struct sizeof_value<const void>
{
static const std::size_t value = sizeof(void*);
};
template <>
struct sizeof_value<volatile void>
{
static const std::size_t value = sizeof(void*);
};
template <>
struct sizeof_value<const volatile void>
{
static const std::size_t value = sizeof(void*);
};
} //namespace interprocess {
} //namespace boost {

View File

@@ -14,13 +14,15 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <cstddef>
#include <cstring>
#include <memory>
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
# pragma comment( lib, "advapi32.lib" )
#endif
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
# include <cstdarg>
# include <boost/detail/interlocked.hpp>
#else
@@ -37,6 +39,7 @@ namespace winapi {
static const unsigned long infinite_time = 0xFFFFFFFF;
static const unsigned long error_already_exists = 183L;
static const unsigned long error_file_not_found = 2u;
static const unsigned long error_no_more_files = 18u;
static const unsigned long semaphore_all_access = (0x000F0000L)|(0x00100000L)|0x3;
static const unsigned long mutex_all_access = (0x000F0000L)|(0x00100000L)|0x0001;
@@ -62,6 +65,15 @@ static const unsigned long file_map_copy = section_query;
static const unsigned long file_map_write = section_map_write;
static const unsigned long file_map_read = section_map_read;
static const unsigned long file_map_all_access = section_all_access;
static const unsigned long delete_access = 0x00010000L;
static const unsigned long file_flag_backup_semantics = 0x02000000;
static const long file_flag_delete_on_close = 0x04000000;
//Native API constants
static const unsigned long file_open_for_backup_intent = 0x00004000;
static const int file_share_valid_flags = 0x00000007;
static const long file_delete_on_close = 0x00001000L;
static const long obj_case_insensitive = 0x00000040L;
static const unsigned long movefile_copy_allowed = 0x02;
static const unsigned long movefile_delay_until_reboot = 0x04;
@@ -74,6 +86,15 @@ 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;
@@ -109,8 +130,6 @@ 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_attribute_temporary = 0x00000100;
static const unsigned long file_begin = 0;
static const unsigned long file_current = 1;
static const unsigned long file_end = 2;
@@ -120,6 +139,13 @@ 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;
} //namespace winapi {
} //namespace interprocess {
} //namespace boost {
@@ -151,6 +177,20 @@ struct interprocess_filetime
unsigned long dwHighDateTime;
};
struct win32_find_data_t
{
unsigned long dwFileAttributes;
interprocess_filetime ftCreationTime;
interprocess_filetime ftLastAccessTime;
interprocess_filetime ftLastWriteTime;
unsigned long nFileSizeHigh;
unsigned long nFileSizeLow;
unsigned long dwReserved0;
unsigned long dwReserved1;
char cFileName[MaxPath];
char cAlternateFileName[14];
};
struct interprocess_security_attributes
{
unsigned long nLength;
@@ -208,6 +248,126 @@ typedef struct _interprocess_security_descriptor
interprocess_acl *Dacl;
} interprocess_security_descriptor;
enum file_information_class_t {
file_directory_information = 1,
file_full_directory_information,
file_both_directory_information,
file_basic_information,
file_standard_information,
file_internal_information,
file_ea_information,
file_access_information,
file_name_information,
file_rename_information,
file_link_information,
file_names_information,
file_disposition_information,
file_position_information,
file_full_ea_information,
file_mode_information,
file_alignment_information,
file_all_information,
file_allocation_information,
file_end_of_file_information,
file_alternate_name_information,
file_stream_information,
file_pipe_information,
file_pipe_local_information,
file_pipe_remote_information,
file_mailslot_query_information,
file_mailslot_set_information,
file_compression_information,
file_copy_on_write_information,
file_completion_information,
file_move_cluster_information,
file_quota_information,
file_reparse_point_information,
file_network_open_information,
file_object_id_information,
file_tracking_information,
file_ole_directory_information,
file_content_index_information,
file_inherit_content_index_information,
file_ole_information,
file_maximum_information
};
struct file_name_information_t {
unsigned long FileNameLength;
wchar_t FileName[1];
};
struct file_rename_information_t {
int Replace;
void *RootDir;
unsigned long FileNameLength;
wchar_t FileName[1];
};
struct unicode_string_t {
unsigned short Length;
unsigned short MaximumLength;
wchar_t *Buffer;
};
struct object_attributes_t {
unsigned long Length;
void * RootDirectory;
unicode_string_t *ObjectName;
unsigned long Attributes;
void *SecurityDescriptor;
void *SecurityQualityOfService;
};
struct io_status_block_t {
union {
long Status;
void *Pointer;
};
unsigned long *Information;
};
union system_timeofday_information
{
struct data_t
{
__int64 liKeBootTime;
__int64 liKeSystemTime;
__int64 liExpTimeZoneBias;
unsigned long uCurrentTimeZoneId;
unsigned long dwReserved;
} data;
unsigned char Reserved1[SystemTimeOfDayInfoLength];
};
enum system_information_class {
system_basic_information = 0,
system_performance_information = 2,
system_time_of_day_information = 3,
system_process_information = 5,
system_processor_performance_information = 8,
system_interrupt_information = 23,
system_exception_information = 33,
system_registry_quota_information = 37,
system_lookaside_information = 45
};
enum object_information_class
{
object_basic_information,
object_name_information,
object_type_information,
object_all_information,
object_data_information
};
struct object_name_information_t
{
unicode_string_t Name;
wchar_t NameBuffer[1];
};
//Some windows API declarations
extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
@@ -220,6 +380,9 @@ extern "C" __declspec(dllimport) int __stdcall DuplicateHandle
, void *hTargetProcessHandle, void **lpTargetHandle
, unsigned long dwDesiredAccess, int bInheritHandle
, unsigned long dwOptions);
extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data_t *lpFindFileData);
extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data_t *lpFindFileData);
extern "C" __declspec(dllimport) int __stdcall FindClose(void *hFindFile);
extern "C" __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(interprocess_filetime*);
extern "C" __declspec(dllimport) int __stdcall FileTimeToLocalFileTime(const interprocess_filetime *in, const interprocess_filetime *out);
extern "C" __declspec(dllimport) void * __stdcall CreateMutexA(interprocess_security_attributes*, int, const char *);
@@ -245,6 +408,7 @@ extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA
std::va_list *Arguments);
extern "C" __declspec(dllimport) void *__stdcall LocalFree (void *);
extern "C" __declspec(dllimport) int __stdcall CreateDirectoryA(const char *, interprocess_security_attributes*);
extern "C" __declspec(dllimport) int __stdcall RemoveDirectoryA(const char *lpPathName);
extern "C" __declspec(dllimport) int __stdcall GetTempPathA(unsigned long length, char *buffer);
extern "C" __declspec(dllimport) int __stdcall CreateDirectory(const char *, interprocess_security_attributes*);
extern "C" __declspec(dllimport) int __stdcall SetFileValidData(void *, __int64 size);
@@ -257,6 +421,25 @@ extern "C" __declspec(dllimport) int __stdcall UnlockFileEx(void *hnd, unsigned
extern "C" __declspec(dllimport) int __stdcall WriteFile(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped);
extern "C" __declspec(dllimport) int __stdcall InitializeSecurityDescriptor(interprocess_security_descriptor *pSecurityDescriptor, unsigned long dwRevision);
extern "C" __declspec(dllimport) int __stdcall SetSecurityDescriptorDacl(interprocess_security_descriptor *pSecurityDescriptor, int bDaclPresent, interprocess_acl *pDacl, int bDaclDefaulted);
extern "C" __declspec(dllimport) void *__stdcall LoadLibraryA(const char *);
extern "C" __declspec(dllimport) int __stdcall FreeLibrary(void *);
extern "C" __declspec(dllimport) void *__stdcall GetProcAddress(void *, const char*);
extern "C" __declspec(dllimport) void *__stdcall GetModuleHandleA(const char*);
//API function typedefs
//Pointer to functions
typedef long (__stdcall *NtDeleteFile_t)(object_attributes_t *ObjectAttributes);
typedef long (__stdcall *NtSetInformationFile_t)(void *FileHandle, io_status_block_t *IoStatusBlock, void *FileInformation, unsigned long Length, int FileInformationClass );
typedef long (__stdcall *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 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 unsigned long (__stdcall * GetMappedFileName_t)(void *, void *, wchar_t *, unsigned long);
} //namespace winapi {
} //namespace interprocess {
@@ -298,6 +481,15 @@ static inline unsigned long get_current_process_id()
static inline unsigned int close_handle(void* handle)
{ return CloseHandle(handle); }
static inline void * find_first_file(const char *lpFileName, win32_find_data_t *lpFindFileData)
{ return FindFirstFileA(lpFileName, lpFindFileData); }
static inline bool find_next_file(void *hFindFile, win32_find_data_t *lpFindFileData)
{ return FindNextFileA(hFindFile, lpFindFileData) != 0; }
static inline bool find_close(void *handle)
{ return FindClose(handle) != 0; }
static inline bool duplicate_current_process_handle
(void *hSourceHandle, void **lpTargetHandle)
{
@@ -384,6 +576,9 @@ static inline bool get_file_size(void *handle, __int64 &size)
static inline bool create_directory(const char *name, interprocess_security_attributes* security)
{ return 0 != CreateDirectoryA(name, security); }
static inline bool remove_directory(const char *lpPathName)
{ return 0 != RemoveDirectoryA(lpPathName); }
static inline unsigned long get_temp_path(unsigned long length, char *buffer)
{ return GetTempPathA(length, buffer); }
@@ -417,6 +612,274 @@ static inline long interlocked_exchange_add(long volatile* addend, long value)
static inline long interlocked_exchange(long volatile* addend, long value)
{ return BOOST_INTERLOCKED_EXCHANGE(const_cast<long*>(addend), value); }
//Forward functions
static inline void *load_library(const char *name)
{ return LoadLibraryA(name); }
static inline bool free_library(void *module)
{ return 0 != FreeLibrary(module); }
static inline void *get_proc_address(void *module, const char *name)
{ return GetProcAddress(module, name); }
static inline void *get_current_process()
{ return GetCurrentProcess(); }
static inline void *get_module_handle(const char *name)
{ return GetModuleHandleA(name); }
static inline void initialize_object_attributes
( object_attributes_t *pobject_attr, unicode_string_t *name
, unsigned long attr, void *rootdir, void *security_descr)
{
pobject_attr->Length = sizeof(object_attributes_t);
pobject_attr->RootDirectory = rootdir;
pobject_attr->Attributes = attr;
pobject_attr->ObjectName = name;
pobject_attr->SecurityDescriptor = security_descr;
pobject_attr->SecurityQualityOfService = 0;
}
static inline void rtl_init_empty_unicode_string(unicode_string_t *ucStr, wchar_t *buf, unsigned short bufSize)
{
ucStr->Buffer = buf;
ucStr->Length = 0;
ucStr->MaximumLength = bufSize;
}
//Complex winapi based functions...
//pszFilename must have room for at least MaxPath+1 characters
static 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;
class library_unloader
{
void *lib_;
public:
library_unloader(void *module) : lib_(module){}
~library_unloader(){ free_library(lib_); }
} unloader(hiPSAPI);
// Pointer to function getMappedFileName() in PSAPI.DLL
GetMappedFileName_t pfGMFN =
(GetMappedFileName_t)get_proc_address(hiPSAPI, "GetMappedFileNameW");
if (! pfGMFN){
return 0; // Failed: unexpected error
}
bool bSuccess = false;
// Create a file mapping object.
void * hFileMap = create_file_mapping(hFile, page_readonly, 0, 1, 0);
if(hFileMap)
{
// Create a file mapping to get the file name.
void* pMem = map_view_of_file_ex(hFileMap, file_map_read, 0, 0, 1, 0);
if (pMem){
out_length = pfGMFN(get_current_process(), pMem, pszFilename, MaxPath);
if(out_length){
bSuccess = true;
}
unmap_view_of_file(pMem);
}
close_handle(hFileMap);
}
return(bSuccess);
}
static inline bool get_system_time_of_day_information(system_timeofday_information &info)
{
NtQuerySystemInformation_t pNtQuerySystemInformation = (NtQuerySystemInformation_t)
get_proc_address(get_module_handle("ntdll.dll"), "NtQuerySystemInformation");
unsigned long res;
long status = pNtQuerySystemInformation(system_time_of_day_information, &info, sizeof(info), &res);
if(status){
return false;
}
return true;
}
static inline bool get_boot_time(unsigned char (&bootstamp) [BootstampLength])
{
system_timeofday_information info;
bool ret = get_system_time_of_day_information(info);
if(!ret){
return false;
}
std::memcpy(&bootstamp[0], &info.Reserved1, sizeof(bootstamp));
return true;
}
static inline bool get_boot_and_system_time(unsigned char (&bootsystemstamp) [BootAndSystemstampLength])
{
system_timeofday_information info;
bool ret = get_system_time_of_day_information(info);
if(!ret){
return false;
}
std::memcpy(&bootsystemstamp[0], &info.Reserved1, sizeof(bootsystemstamp));
return true;
}
static inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s) //will write BootstampLength chars
{
if(s < (BootstampLength*2))
return false;
system_timeofday_information info;
bool ret = get_system_time_of_day_information(info);
if(!ret){
return false;
}
const char Characters [] =
{ '0', '1', '2', '3', '4', '5', '6', '7'
, '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
std::size_t char_counter = 0;
for(std::size_t i = 0; i != static_cast<std::size_t>(BootstampLength); ++i){
bootstamp_str[char_counter++] = Characters[(info.Reserved1[i]&0xF0)>>4];
bootstamp_str[char_counter++] = Characters[(info.Reserved1[i]&0x0F)];
}
s = BootstampLength*2;
return true;
}
static inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t &s) //will write BootAndSystemstampLength chars
{
if(s < (BootAndSystemstampLength*2))
return false;
system_timeofday_information info;
bool ret = get_system_time_of_day_information(info);
if(!ret){
return false;
}
const wchar_t Characters [] =
{ L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7'
, L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' };
std::size_t char_counter = 0;
for(std::size_t i = 0; i != static_cast<std::size_t>(BootAndSystemstampLength); ++i){
bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0xF0)>>4];
bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0x0F)];
}
s = BootAndSystemstampLength*2;
return true;
}
static inline bool unlink_file(const char *filename)
{
try{
NtSetInformationFile_t pNtSetInformationFile =
(NtSetInformationFile_t)get_proc_address(get_module_handle("ntdll.dll"), "NtSetInformationFile");
if(!pNtSetInformationFile){
return false;
}
NtQueryObject_t pNtQueryObject =
(NtQueryObject_t)get_proc_address(get_module_handle("ntdll.dll"), "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);
if(fh == invalid_handle_value){
return false;
}
class handle_closer
{
void *handle_;
public:
handle_closer(void *handle) : handle_(handle){}
~handle_closer(){ close_handle(handle_); }
} handle_closer(fh);
const std::size_t CharArraySize = 32767; //Max name length
union mem_t
{
object_name_information_t name;
struct ren_t
{
file_rename_information_t info;
wchar_t buf[CharArraySize];
} ren;
};
class auto_ptr
{
public:
explicit auto_ptr(mem_t *ptr) : ptr_(ptr){}
~auto_ptr(){ delete ptr_; }
mem_t *get() const{ return (ptr_); }
mem_t *operator->() const{ return this->get(); }
private:
mem_t *ptr_;
} pmem(new mem_t);
file_rename_information_t *pfri = (file_rename_information_t*)&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(mem_t), &size)){
return false;
}
//Copy filename to the rename member
std::memmove(pmem->ren.info.FileName, pmem->name.Name.Buffer, pmem->name.Name.Length);
std::size_t filename_string_length = pmem->name.Name.Length/sizeof(wchar_t);
//Second step: obtain the complete native-nt filename
//if(!get_file_name_from_handle_function(fh, pfri->FileName, RenMaxNumChars, filename_string_length)){
//return 0;
//}
//Add trailing mark
if((RenMaxNumChars-filename_string_length) < (SystemTimeOfDayInfoLength*2)){
return false;
}
//Search '\\' character to replace it
for(std::size_t i = filename_string_length; i != 0; --filename_string_length){
if(pmem->ren.info.FileName[--i] == L'\\')
break;
}
//Add random number
std::size_t s = RenMaxNumChars - filename_string_length;
if(!get_boot_and_system_time_wstr(&pfri->FileName[filename_string_length], s)){
return false;
}
filename_string_length += s;
//Fill rename information (FileNameLength is in bytes)
pfri->FileNameLength = static_cast<unsigned long>(sizeof(wchar_t)*(filename_string_length));
pfri->Replace = 1;
pfri->RootDir = 0;
//Final step: change the name of the in-use file:
io_status_block_t io;
if(0 != pNtSetInformationFile(fh, &io, pfri, sizeof(mem_t::ren_t), file_rename_information)){
return false;
}
return true;
}
catch(...){
return false;
}
}
} //namespace winapi
} //namespace interprocess
} //namespace boost

View File

@@ -8,40 +8,46 @@
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_PTR_WRKRND_HPP
#define BOOST_INTERPROCESS_PTR_WRKRND_HPP
#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
#define BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
#include <boost/interprocess/detail/config_begin.hpp>
#undef BOOST_DISABLE_WIN32
#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
#if !(defined BOOST_WINDOWS) || (defined BOOST_DISABLE_WIN32)
#define BOOST_INTERPROCESS_WINDOWS
/*
#if !defined(_MSC_EXTENSIONS)
#error "Turn on Microsoft language extensions (_MSC_EXTENSIONS) to be able to call Windows API functions"
#endif
*/
#endif
#if !(defined BOOST_INTERPROCESS_WINDOWS)
#include <unistd.h>
#if defined(_POSIX_THREAD_PROCESS_SHARED)
# if !((_XOPEN_VERSION >= 600) && (_POSIX_THREAD_PROCESS_SHARED - 0 <= 0))
#if ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0)
//Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it.
//Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seems to work.
# if !defined(__CYGWIN__) && !defined(__APPLE__)
# define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
# endif
# endif
#endif
#if defined(_POSIX_BARRIERS)
# if !((_XOPEN_VERSION >= 600) && (_POSIX_BARRIERS - 0 <= 0))
#endif
#if ((_POSIX_BARRIERS - 0) > 0)
# define BOOST_INTERPROCESS_POSIX_BARRIERS
# endif
#endif
#if defined(_POSIX_SEMAPHORES)
# if !((_XOPEN_VERSION >= 600) && (_POSIX_SEMAPHORES - 0 <= 0))
# define BOOST_INTERPROCESS_POSIX_SEMAPHORES
#if ((_POSIX_SEMAPHORES - 0) > 0)
# define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
# if defined(__CYGWIN__)
#define BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK
# endif
# endif
#elif defined(__APPLE__)
# define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
#endif
#if ((defined _V6_ILP32_OFFBIG) &&(_V6_ILP32_OFFBIG - 0 > 0)) ||\
@@ -56,40 +62,41 @@
#else
#endif
#if defined(_POSIX_SHARED_MEMORY_OBJECTS)
# if !((_XOPEN_VERSION >= 600) && (_POSIX_SHARED_MEMORY_OBJECTS - 0 <= 0))
#if ((_POSIX_SHARED_MEMORY_OBJECTS - 0) > 0)
# define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
# endif
#else
//VMS and MACOS don't define it but the have shm_open/close interface
# if defined(__vms)
# if __CRTL_VER >= 70200000
# define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
# endif
# define BOOST_INTERPROCESS_SYSTEM_V_SHARED_MEMORY_OBJECTS
//Mac OS has some non-conformant features like names limited to SHM_NAME_MAX
//# elif defined (__APPLE__)
//# define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
# endif
#endif
#if defined(_POSIX_TIMEOUTS)
# if !((_XOPEN_VERSION >= 600) && (_POSIX_TIMEOUTS - 0 <= 0))
#if ((_POSIX_TIMEOUTS - 0) > 0)
# define BOOST_INTERPROCESS_POSIX_TIMEOUTS
# endif
#endif
//Some systems have filesystem-based resources, so the
//portable "/shmname" format does not work due to permission issues
//For those systems we need to form a path to a temporary directory:
// hp-ux tru64 vms freebsd
#if defined(__hpux) || defined(__osf__) || defined(__vms) || defined(__FreeBSD__)
#define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_RESOURCES
#endif
#ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
//Some systems have filesystem-based shared memory, so the
//portable "/shmname" format does not work due to permission issues
//For those systems we need to form a path to a temporary directory:
// hp-ux tru64 vms
#if defined(__hpux) || defined(__osf__) || defined(__vms)
#if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_RESOURCES)
#define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
#endif
#endif
#ifdef BOOST_INTERPROCESS_POSIX_SEMAPHORES
//Some systems have filesystem-based shared memory, so the
//portable "/semname" format does not work due to permission issues
//For those systems we need to form a path to a temporary directory:
// hp-ux tru64 vms
#if defined(__hpux) || defined(__osf__) || defined(__vms)
#ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
#if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_RESOURCES)
#define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
#endif
#endif
@@ -100,34 +107,20 @@
#endif
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)
// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are
// passed on the command line, which in turn defines
// __GXX_EXPERIMENTAL_CXX0X__. Note: __GXX_EXPERIMENTAL_CPP0X__ is
// defined by some very early development versions of GCC 4.3; we will
// remove this part of the check in the near future.
# if defined(__GXX_EXPERIMENTAL_CPP0X__) || defined(__GXX_EXPERIMENTAL_CXX0X__)
# define BOOST_INTERPROCESS_RVALUE_REFERENCE
# define BOOST_INTERPROCESS_VARIADIC_TEMPLATES
# if defined(__GLIBCPP__) || defined(__GLIBCXX__)
# define BOOST_INTERPROCESS_RVALUE_PAIR
# endif
# endif
#endif
#if defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && defined(BOOST_INTERPROCESS_VARIADIC_TEMPLATES)
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)\
&& !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
#define BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif
//Now declare some Boost.Interprocess features depending on the implementation
#if defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
#endif
#if defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES
@@ -136,4 +129,4 @@
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_PTR_WRKRND_HPP
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP

View File

@@ -33,7 +33,7 @@
#include <stdarg.h>
#include <string>
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
@@ -42,7 +42,7 @@
# else //ifdef BOOST_HAS_UNISTD_H
# error Unknown platform
# endif //ifdef BOOST_HAS_UNISTD_H
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
//!\file
//!Describes the error numbering of interprocess classes
@@ -52,7 +52,7 @@ namespace interprocess {
/// @cond
static inline int system_error_code() // artifact of POSIX and WINDOWS error reporting
{
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
return winapi::get_last_error();
#else
return errno; // GCC 3.1 won't accept ::errno
@@ -60,7 +60,7 @@ static inline int system_error_code() // artifact of POSIX and WINDOWS error rep
}
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
inline void fill_system_message(int sys_err_code, std::string &str)
{
void *lpMsgBuf;
@@ -110,7 +110,9 @@ enum error_code_t
sem_error,
mode_error,
size_error,
corrupted_error
corrupted_error,
not_such_file_or_directory,
invalid_argument
};
typedef int native_error_t;
@@ -124,7 +126,7 @@ struct ec_xlate
static const ec_xlate ec_table[] =
{
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
{ /*ERROR_ACCESS_DENIED*/5L, security_error },
{ /*ERROR_INVALID_ACCESS*/12L, security_error },
{ /*ERROR_SHARING_VIOLATION*/32L, security_error },
@@ -156,7 +158,7 @@ static const ec_xlate ec_table[] =
{ /*ERROR_OUTOFMEMORY*/14L, out_of_memory_error },
{ /*ERROR_NOT_ENOUGH_MEMORY*/8L, out_of_memory_error },
{ /*ERROR_TOO_MANY_OPEN_FILES*/4L, out_of_resource_error }
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
{ EACCES, security_error },
{ EROFS, read_only_error },
{ EIO, io_error },
@@ -171,8 +173,10 @@ static const ec_xlate ec_table[] =
{ EISDIR, is_directory_error },
{ ENOSPC, out_of_space_error },
{ ENOMEM, out_of_memory_error },
{ EMFILE, out_of_resource_error }
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
{ EMFILE, out_of_resource_error },
{ ENOENT, not_such_file_or_directory },
{ EINVAL, invalid_argument }
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
};
static inline error_code_t lookup_error(native_error_t err)

View File

@@ -21,8 +21,6 @@
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <string> //std::string
#include <cstdio> //std::remove
#include <string>
//!\file
//!Describes file_mapping and mapped region classes
@@ -30,31 +28,19 @@
namespace boost {
namespace interprocess {
///@cond
class file_mapping;
//!Trait class to detect if a type is
//!movable
template<>
struct is_movable<file_mapping>
{
enum { value = true };
};
///@endcond
//!A class that wraps a file-mapping that can be used to
//!create mapped regions from the mapped files
class file_mapping
{
/// @cond
//Non-copyable and non-assignable
file_mapping(const file_mapping &);
file_mapping &operator=(const file_mapping &);
file_mapping(file_mapping &);
file_mapping &operator=(file_mapping &);
/// @endcond
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(file_mapping)
//!Constructs an empty file mapping.
//!Does not throw
file_mapping();
@@ -68,41 +54,23 @@ class file_mapping
//!Moves the ownership of "moved"'s file mapping object to *this.
//!After the call, "moved" does not represent any file mapping object.
//!Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
file_mapping(detail::moved_object<file_mapping> moved)
: m_handle(file_handle_t(detail::invalid_file()))
{ this->swap(moved.get()); }
#else
file_mapping(file_mapping &&moved)
file_mapping(BOOST_INTERPROCESS_RV_REF(file_mapping) moved)
: m_handle(file_handle_t(detail::invalid_file()))
{ this->swap(moved); }
#endif
//!Moves the ownership of "moved"'s file mapping to *this.
//!After the call, "moved" does not represent any file mapping.
//!Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
file_mapping &operator=(detail::moved_object<file_mapping> m_other)
{
file_mapping &moved = m_other.get();
#else
file_mapping &operator=(file_mapping &&moved)
{
#endif
file_mapping tmp(detail::move_impl(moved));
file_mapping &operator=(BOOST_INTERPROCESS_RV_REF(file_mapping) moved)
{
file_mapping tmp(boost::interprocess::move(moved));
this->swap(tmp);
return *this;
}
//!Swaps to file_mappings.
//!Does not throw.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
void swap(detail::moved_object<file_mapping> mother)
{ this->swap(mother.get()); }
void swap(file_mapping &other);
#else
void swap(file_mapping &&other);
#endif
//!Returns access mode
//!used in the constructor
@@ -120,6 +88,12 @@ class file_mapping
//!used in the constructor.
const char *get_name() const;
//!Removes the file named "filename" even if it's been memory mapped.
//!Returns true on success.
//!The function might fail in some operating systems if the file is
//!being used other processes and no deletion permission was shared.
static bool remove(const char *filename);
/// @cond
private:
//!Closes a previously opened file mapping. Never throws.
@@ -140,11 +114,7 @@ inline file_mapping::~file_mapping()
inline const char *file_mapping::get_name() const
{ return m_filename.c_str(); }
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void file_mapping::swap(file_mapping &other)
#else
inline void file_mapping::swap(file_mapping &&other)
#endif
{
std::swap(m_handle, other.m_handle);
std::swap(m_mode, other.m_mode);
@@ -179,6 +149,9 @@ inline file_mapping::file_mapping
m_mode = mode;
}
inline bool file_mapping::remove(const char *filename)
{ return detail::delete_file(filename); }
///@cond
inline void file_mapping::priv_close()
@@ -192,7 +165,7 @@ inline void file_mapping::priv_close()
///@endcond
//!A class that stores the name of a file
//!and call std::remove(name) in its destructor
//!and tries to remove it in its destructor
//!Useful to remove temporary files in the presence
//!of exceptions
class remove_file_on_destroy
@@ -204,7 +177,7 @@ class remove_file_on_destroy
{}
~remove_file_on_destroy()
{ std::remove(m_name); }
{ detail::delete_file(m_name); }
};
} //namespace interprocess {

View File

@@ -176,7 +176,7 @@ class iunordered_set_index
return old_size;
std::size_t received_size;
if(!alloc.allocation_command
(try_shrink_in_place | nothrow_allocation, old_size, new_size, received_size, buckets).first){
(boost::interprocess::try_shrink_in_place | boost::interprocess::nothrow_allocation, old_size, new_size, received_size, buckets).first){
return old_size;
}
@@ -188,7 +188,7 @@ class iunordered_set_index
}
bucket_ptr shunk_p = alloc.allocation_command
(shrink_in_place | nothrow_allocation, received_size, received_size, received_size, buckets).first;
(boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, received_size, received_size, received_size, buckets).first;
BOOST_ASSERT(buckets == shunk_p);
bucket_ptr buckets_init = buckets + received_size;
@@ -205,7 +205,7 @@ class iunordered_set_index
std::size_t received_size;
std::pair<bucket_ptr, bool> ret =
alloc.allocation_command
(expand_fwd | allocate_new, new_num, new_num, received_size, old_buckets);
(boost::interprocess::expand_fwd | boost::interprocess::allocate_new, new_num, new_num, received_size, old_buckets);
if(ret.first == old_buckets){
bucket_ptr buckets_init = old_buckets + old_num;
for(std::size_t i = 0; i < (new_num - old_num); ++i){

View File

@@ -11,12 +11,12 @@
#ifndef BOOST_INTERPROCESS_FWD_HPP
#define BOOST_INTERPROCESS_FWD_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
#if defined (_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
//#include <boost/interprocess/detail/config_begin.hpp>
//#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <cstddef>
@@ -61,9 +61,9 @@ namespace boost { namespace interprocess {
class shared_memory_object;
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if defined (BOOST_INTERPROCESS_WINDOWS)
class windows_shared_memory;
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
//////////////////////////////////////////////////////////////////////////////
// mapped file/mapped region/mapped_file
@@ -113,6 +113,9 @@ class scoped_lock;
template <class SharableMutex>
class sharable_lock;
template <class UpgradableMutex>
class upgradable_lock;
//////////////////////////////////////////////////////////////////////////////
// STL compatible allocators
//////////////////////////////////////////////////////////////////////////////
@@ -230,7 +233,7 @@ wmanaged_shared_memory;
// Windows shared memory managed memory classes
//////////////////////////////////////////////////////////////////////////////
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if defined (BOOST_INTERPROCESS_WINDOWS)
template <class CharType
,class MemoryAlgorithm
@@ -249,7 +252,26 @@ typedef basic_managed_windows_shared_memory
,iset_index>
wmanaged_windows_shared_memory;
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#else
template <class CharType
,class MemoryAlgorithm
,template<class IndexConfig> class IndexType>
class basic_managed_xsi_shared_memory;
typedef basic_managed_xsi_shared_memory
<char
,rbtree_best_fit<mutex_family>
,iset_index>
managed_xsi_shared_memory;
typedef basic_managed_xsi_shared_memory
<wchar_t
,rbtree_best_fit<mutex_family>
,iset_index>
wmanaged_xsi_shared_memory;
#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
//////////////////////////////////////////////////////////////////////////////
// Fixed address shared memory
@@ -382,98 +404,12 @@ class weak_ptr;
class message_queue;
//////////////////////////////////////////////////////////////////////////////
// Containers
//////////////////////////////////////////////////////////////////////////////
//vector class
template <class T
,class A = std::allocator<T> >
class vector;
//vector class
template <class T
,class A = std::allocator<T> >
class deque;
//list class
template <class T
,class A = std::allocator<T> >
class list;
//slist class
template <class T
,class Alloc = std::allocator<T> >
class slist;
//set class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class set;
//multiset class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class multiset;
//map class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<const Key, T> > >
class map;
//multimap class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<const Key, T> > >
class multimap;
//flat_set class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class flat_set;
//flat_multiset class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class flat_multiset;
//flat_map class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<Key, T> > >
class flat_map;
//flat_multimap class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<Key, T> > >
class flat_multimap;
//basic_string class
template <class CharT
,class Traits = std::char_traits<CharT>
,class Alloc = std::allocator<CharT> >
class basic_string;
//string class
typedef basic_string
<char
,std::char_traits<char>
,std::allocator<char> >
string;
}} //namespace boost { namespace interprocess {
//#include <boost/interprocess/detail/config_end.hpp>
//////////////////////////////////////////////////////////////////////////////
// CONTAINERS
//////////////////////////////////////////////////////////////////////////////
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_FWD_HPP

View File

@@ -43,9 +43,12 @@ class basic_managed_external_buffer
/// @cond
typedef detail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType> base_t;
basic_managed_external_buffer(basic_managed_external_buffer&);
basic_managed_external_buffer & operator=(basic_managed_external_buffer&);
/// @endcond
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_managed_external_buffer)
//!Default constructor. Does nothing.
//!Useful in combination with move semantics
@@ -75,25 +78,15 @@ class basic_managed_external_buffer
}
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
basic_managed_external_buffer(detail::moved_object<basic_managed_external_buffer> mother)
basic_managed_external_buffer(BOOST_INTERPROCESS_RV_REF(basic_managed_external_buffer) moved)
{
basic_managed_external_buffer &moved = mother.get();
#else
basic_managed_external_buffer(basic_managed_external_buffer &&moved)
{
#endif
this->swap(moved);
}
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
basic_managed_external_buffer &operator=(detail::moved_object<basic_managed_external_buffer> moved)
#else
basic_managed_external_buffer &operator=(basic_managed_external_buffer &&moved)
#endif
basic_managed_external_buffer &operator=(BOOST_INTERPROCESS_RV_REF(basic_managed_external_buffer) moved)
{
basic_managed_external_buffer tmp(detail::move_impl(moved));
basic_managed_external_buffer tmp(boost::interprocess::move(moved));
this->swap(tmp);
return *this;
}
@@ -103,36 +96,10 @@ class basic_managed_external_buffer
//!Swaps the ownership of the managed heap memories managed by *this and other.
//!Never throws.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
void swap(detail::moved_object<basic_managed_external_buffer> mother)
{ this->swap(mother.get()); }
void swap(basic_managed_external_buffer &other)
#else
void swap(basic_managed_external_buffer &&other)
#endif
{ base_t::swap(other); }
};
///@cond
//!Trait class to detect if a type is
//!movable
template
<
class CharType,
class AllocationAlgorithm,
template<class IndexConfig> class IndexType
>
struct is_movable<basic_managed_external_buffer
<CharType, AllocationAlgorithm, IndexType>
>
{
static const bool value = true;
};
///@endcond
} //namespace interprocess {
} //namespace boost {

View File

@@ -46,9 +46,12 @@ class basic_managed_heap_memory
typedef detail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType> base_t;
basic_managed_heap_memory(basic_managed_heap_memory&);
basic_managed_heap_memory & operator=(basic_managed_heap_memory&);
/// @endcond
public: //functions
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_managed_heap_memory)
//!Default constructor. Does nothing.
//!Useful in combination with move semantics
@@ -71,26 +74,13 @@ class basic_managed_heap_memory
}
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
basic_managed_heap_memory
(detail::moved_object<basic_managed_heap_memory> mother)
{
basic_managed_heap_memory &moved = mother.get();
#else
basic_managed_heap_memory(basic_managed_heap_memory &&moved)
{
#endif
this->swap(moved);
}
basic_managed_heap_memory(BOOST_INTERPROCESS_RV_REF(basic_managed_heap_memory) moved)
{ this->swap(moved); }
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
basic_managed_heap_memory &operator=(detail::moved_object<basic_managed_heap_memory> moved)
#else
basic_managed_heap_memory &operator=(basic_managed_heap_memory &&moved)
#endif
basic_managed_heap_memory &operator=(BOOST_INTERPROCESS_RV_REF(basic_managed_heap_memory) moved)
{
basic_managed_heap_memory tmp(detail::move_impl(moved));
basic_managed_heap_memory tmp(boost::interprocess::move(moved));
this->swap(tmp);
return *this;
}
@@ -125,13 +115,7 @@ class basic_managed_heap_memory
//!Swaps the ownership of the managed heap memories managed by *this and other.
//!Never throws.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
void swap(detail::moved_object<basic_managed_heap_memory> mother)
{ this->swap(mother.get()); }
void swap(basic_managed_heap_memory &other)
#else
void swap(basic_managed_heap_memory &&other)
#endif
{
base_t::swap(other);
m_heapmem.swap(other.m_heapmem);
@@ -150,27 +134,8 @@ class basic_managed_heap_memory
/// @endcond
};
///@cond
//!Trait class to detect if a type is
//!movable
template
<
class CharType,
class AllocationAlgorithm,
template<class IndexConfig> class IndexType
>
struct is_movable<basic_managed_heap_memory
<CharType, AllocationAlgorithm, IndexType>
>
{
static const bool value = true;
};
///@endcond
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -47,6 +47,8 @@ class basic_managed_mapped_file
<CharType, AllocationAlgorithm, IndexType,
detail::managed_open_or_create_impl<detail::file_wrapper>::ManagedOpenOrCreateUserOffset> base_t;
typedef detail::file_wrapper device_type;
basic_managed_mapped_file(basic_managed_mapped_file&);
basic_managed_mapped_file & operator=(basic_managed_mapped_file&);
private:
@@ -61,6 +63,7 @@ class basic_managed_mapped_file
/// @endcond
public: //functions
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_managed_mapped_file)
//!Creates mapped file and creates and places the segment manager.
//!This can throw.
@@ -118,27 +121,16 @@ class basic_managed_mapped_file
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
basic_managed_mapped_file
(detail::moved_object<basic_managed_mapped_file> mother)
basic_managed_mapped_file(BOOST_INTERPROCESS_RV_REF(basic_managed_mapped_file) moved)
{
basic_managed_mapped_file &moved = mother.get();
#else
basic_managed_mapped_file(basic_managed_mapped_file &&moved)
{
#endif
this->swap(moved);
}
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
basic_managed_mapped_file &operator=(detail::moved_object<basic_managed_mapped_file> moved)
#else
basic_managed_mapped_file &operator=(basic_managed_mapped_file &&moved)
#endif
basic_managed_mapped_file &operator=(BOOST_INTERPROCESS_RV_REF(basic_managed_mapped_file) moved)
{
basic_managed_mapped_file tmp(detail::move_impl(moved));
basic_managed_mapped_file tmp(boost::interprocess::move(moved));
this->swap(tmp);
return *this;
}
@@ -154,14 +146,7 @@ class basic_managed_mapped_file
//!Swaps the ownership of the managed mapped memories managed by *this and other.
//!Never throws.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
void swap(detail::moved_object<basic_managed_mapped_file> mother)
{ this->swap(mother.get()); }
void swap(basic_managed_mapped_file &other)
#else
void swap(basic_managed_mapped_file &&other)
#endif
{
base_t::swap(other);
m_mfile.swap(other.m_mfile);
@@ -214,27 +199,7 @@ class basic_managed_mapped_file
/// @endcond
};
///@cond
//!Trait class to detect if a type is
//!movable
template
<
class CharType,
class AllocationAlgorithm,
template<class IndexConfig> class IndexType
>
struct is_movable<basic_managed_mapped_file
<CharType, AllocationAlgorithm, IndexType>
>
{
static const bool value = true;
};
///@endcond
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -60,9 +60,12 @@ class basic_managed_shared_memory
private:
typedef typename base_t::char_ptr_holder_t char_ptr_holder_t;
basic_managed_shared_memory(basic_managed_shared_memory&);
basic_managed_shared_memory & operator=(basic_managed_shared_memory&);
/// @endcond
public: //functions
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_managed_shared_memory)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
@@ -134,14 +137,8 @@ class basic_managed_shared_memory
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
basic_managed_shared_memory(detail::moved_object<basic_managed_shared_memory> mother)
basic_managed_shared_memory(BOOST_INTERPROCESS_RV_REF(basic_managed_shared_memory) moved)
{
basic_managed_shared_memory &moved = mother.get();
#else
basic_managed_shared_memory(basic_managed_shared_memory &&moved)
{
#endif
basic_managed_shared_memory tmp;
this->swap(moved);
tmp.swap(moved);
@@ -149,26 +146,16 @@ class basic_managed_shared_memory
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
basic_managed_shared_memory &operator=(detail::moved_object<basic_managed_shared_memory> moved)
#else
basic_managed_shared_memory &operator=(basic_managed_shared_memory &&moved)
#endif
basic_managed_shared_memory &operator=(BOOST_INTERPROCESS_RV_REF(basic_managed_shared_memory) moved)
{
basic_managed_shared_memory tmp(detail::move_impl(moved));
basic_managed_shared_memory tmp(boost::interprocess::move(moved));
this->swap(tmp);
return *this;
}
//!Swaps the ownership of the managed shared memories managed by *this and other.
//!Never throws.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
void swap(detail::moved_object<basic_managed_shared_memory> mother)
{ this->swap(mother.get()); }
void swap(basic_managed_shared_memory &other)
#else
void swap(basic_managed_shared_memory &&other)
#endif
{
base_t::swap(other);
base2_t::swap(other);
@@ -179,20 +166,20 @@ class basic_managed_shared_memory
//!
//!This function is not synchronized so no other thread or process should
//!be reading or writing the file
static bool grow(const char *filename, std::size_t extra_bytes)
static bool grow(const char *shmname, std::size_t extra_bytes)
{
return base_t::template grow
<basic_managed_shared_memory>(filename, extra_bytes);
<basic_managed_shared_memory>(shmname, extra_bytes);
}
//!Tries to resize the managed shared memory to minimized the size of the file.
//!
//!This function is not synchronized so no other thread or process should
//!be reading or writing the file
static bool shrink_to_fit(const char *filename)
static bool shrink_to_fit(const char *shmname)
{
return base_t::template shrink_to_fit
<basic_managed_shared_memory>(filename);
<basic_managed_shared_memory>(shmname);
}
/// @cond
@@ -214,25 +201,6 @@ class basic_managed_shared_memory
/// @endcond
};
///@cond
//!Trait class to detect if a type is
//!movable
template
<
class CharType,
class AllocationAlgorithm,
template<class IndexConfig> class IndexType
>
struct is_movable<basic_managed_shared_memory
<CharType, AllocationAlgorithm, IndexType>
>
{
static const bool value = true;
};
///@endcond
} //namespace interprocess {
} //namespace boost {

View File

@@ -60,9 +60,13 @@ class basic_managed_windows_shared_memory
private:
typedef typename base_t::char_ptr_holder_t char_ptr_holder_t;
basic_managed_windows_shared_memory(basic_managed_windows_shared_memory&);
basic_managed_windows_shared_memory & operator=(basic_managed_windows_shared_memory&);
/// @endcond
public: //functions
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_managed_windows_shared_memory)
//!Default constructor. Does nothing.
//!Useful in combination with move semantics
@@ -121,24 +125,15 @@ class basic_managed_windows_shared_memory
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
basic_managed_windows_shared_memory
(detail::moved_object<basic_managed_windows_shared_memory> moved)
{ this->swap(moved.get()); }
#else
basic_managed_windows_shared_memory(basic_managed_windows_shared_memory &&moved)
(BOOST_INTERPROCESS_RV_REF(basic_managed_windows_shared_memory) moved)
{ this->swap(moved); }
#endif
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
basic_managed_windows_shared_memory &operator=(detail::moved_object<basic_managed_windows_shared_memory> moved)
#else
basic_managed_windows_shared_memory &operator=(basic_managed_windows_shared_memory &&moved)
#endif
basic_managed_windows_shared_memory &operator=(BOOST_INTERPROCESS_RV_REF(basic_managed_windows_shared_memory) moved)
{
basic_managed_windows_shared_memory tmp(detail::move_impl(moved));
basic_managed_windows_shared_memory tmp(boost::interprocess::move(moved));
this->swap(tmp);
return *this;
}
@@ -153,19 +148,14 @@ class basic_managed_windows_shared_memory
//!Swaps the ownership of the managed mapped memories managed by *this and other.
//!Never throws.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
void swap(detail::moved_object<basic_managed_windows_shared_memory> mother)
{ this->swap(mother.get()); }
void swap(basic_managed_windows_shared_memory &other)
#else
void swap(basic_managed_windows_shared_memory &&other)
#endif
{
base_t::swap(other);
m_wshm.swap(other.m_wshm);
}
/// @cond
//!Tries to find a previous named allocation address. Returns a memory
//!buffer and the object count. If not found returned pointer is 0.
//!Never throws.
@@ -185,25 +175,6 @@ class basic_managed_windows_shared_memory
/// @endcond
};
///@cond
//!Trait class to detect if a type is
//!movable
template
<
class CharType,
class AllocationAlgorithm,
template<class IndexConfig> class IndexType
>
struct is_movable<basic_managed_windows_shared_memory
<CharType, AllocationAlgorithm, IndexType>
>
{
static const bool value = true;
};
///@endcond
} //namespace interprocess {
} //namespace boost {

View File

@@ -22,7 +22,7 @@
#include <string>
#include <limits>
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
@@ -31,11 +31,13 @@
# include <unistd.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <sys/shm.h>
# include <cassert>
# else
# error Unknown platform
# endif
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
//!\file
//!Describes memory_mappable and mapped region classes
@@ -55,11 +57,12 @@ class mapped_region
{
/// @cond
//Non-copyable
mapped_region(const mapped_region &);
mapped_region &operator=(const mapped_region &);
mapped_region(mapped_region &);
mapped_region &operator=(mapped_region &);
/// @endcond
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(mapped_region)
//!Creates a mapping region of the mapped memory "mapping", starting in
//!offset "offset", and the mapping's size will be "size". The mapping
@@ -78,11 +81,7 @@ class mapped_region
//!Move constructor. *this will be constructed taking ownership of "other"'s
//!region and "other" will be left in default constructor state.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
mapped_region(detail::moved_object<mapped_region> other);
#else
mapped_region(mapped_region &&other);
#endif
mapped_region(BOOST_INTERPROCESS_RV_REF(mapped_region) other);
//!Destroys the mapped region.
//!Does not throw
@@ -90,11 +89,7 @@ class mapped_region
//!Move assignment. If *this owns a memory mapped region, it will be
//!destroyed and it will take ownership of "other"'s memory mapped region.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
mapped_region &operator=(detail::moved_object<mapped_region> other);
#else
mapped_region &operator=(mapped_region &&other);
#endif
mapped_region &operator=(BOOST_INTERPROCESS_RV_REF(mapped_region) other);
//!Returns the size of the mapping. Note for windows users: If
//!windows_shared_memory is mapped using 0 as the size, it returns 0
@@ -119,13 +114,7 @@ class mapped_region
//!Swaps the mapped_region with another
//!mapped region
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
void swap(detail::moved_object<mapped_region> mother)
{ this->swap(mother.get()); }
void swap(mapped_region &other);
#else
void swap(mapped_region &&other);
#endif
//!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.
@@ -148,8 +137,10 @@ class mapped_region
offset_t m_offset;
offset_t m_extra_offset;
mode_t m_mode;
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
file_handle_t m_file_mapping_hnd;
#if (defined BOOST_INTERPROCESS_WINDOWS)
file_handle_t m_file_mapping_hnd;
#else
bool m_is_xsi;
#endif
friend class detail::interprocess_tester;
@@ -163,14 +154,9 @@ class mapped_region
inline void swap(mapped_region &x, mapped_region &y)
{ x.swap(y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
inline mapped_region &mapped_region::operator=(detail::moved_object<mapped_region> moved)
inline mapped_region &mapped_region::operator=(BOOST_INTERPROCESS_RV_REF(mapped_region) moved)
{
#else
inline mapped_region &mapped_region::operator=(mapped_region &&moved)
{
#endif
mapped_region tmp(detail::move_impl(moved));
mapped_region tmp(boost::interprocess::move(moved));
this->swap(tmp);
return *this;
}
@@ -190,28 +176,19 @@ inline mode_t mapped_region::get_mode() const
inline void* mapped_region::get_address() const
{ return m_base; }
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
inline mapped_region::mapped_region()
: m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only)
, m_file_mapping_hnd(detail::invalid_file())
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
inline mapped_region::mapped_region(detail::moved_object<mapped_region> other)
: m_base(0), m_size(0), m_offset(0)
, m_extra_offset(0)
, m_mode(read_only)
, m_file_mapping_hnd(detail::invalid_file())
{ this->swap(other.get()); }
#else
inline mapped_region::mapped_region(mapped_region &&other)
inline mapped_region::mapped_region(BOOST_INTERPROCESS_RV_REF(mapped_region) other)
: m_base(0), m_size(0), m_offset(0)
, m_extra_offset(0)
, m_mode(read_only)
, m_file_mapping_hnd(detail::invalid_file())
{ this->swap(other); }
#endif
template<int dummy>
inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size()
@@ -264,7 +241,9 @@ inline mapped_region::mapped_region
//Update mapping size if the user does not specify it
if(size == 0){
__int64 total_size;
if(!winapi::get_file_size(detail::file_handle_from_mapping_handle(mapping.get_mapping_handle()), total_size)){
if(!winapi::get_file_size
(detail::file_handle_from_mapping_handle
(mapping.get_mapping_handle()), total_size)){
error_info err(winapi::get_last_error());
throw interprocess_exception(err);
}
@@ -382,11 +361,10 @@ inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbyte
inline void mapped_region::priv_close()
{
if(m_base){
this->flush();
winapi::unmap_view_of_file(static_cast<char*>(m_base) - m_extra_offset);
m_base = 0;
}
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#if (defined BOOST_INTERPROCESS_WINDOWS)
if(m_file_mapping_hnd != detail::invalid_file()){
winapi::close_handle(m_file_mapping_hnd);
m_file_mapping_hnd = detail::invalid_file();
@@ -397,22 +375,15 @@ inline void mapped_region::priv_close()
inline void mapped_region::dont_close_on_destruction()
{}
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
inline mapped_region::mapped_region()
: m_base(MAP_FAILED), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only)
: m_base(MAP_FAILED), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only), m_is_xsi(false)
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
inline mapped_region::mapped_region(detail::moved_object<mapped_region> other)
: m_base(MAP_FAILED), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only)
{ this->swap(other.get()); }
#else
inline mapped_region::mapped_region(mapped_region &&other)
: m_base(MAP_FAILED), m_size(0), m_offset(0), m_mode(read_only)
, m_extra_offset(0)
inline mapped_region::mapped_region(BOOST_INTERPROCESS_RV_REF(mapped_region) other)
: m_base(MAP_FAILED), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only), m_is_xsi(false)
{ this->swap(other); }
#endif
template<int dummy>
inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size()
@@ -425,13 +396,55 @@ inline mapped_region::mapped_region
offset_t offset,
std::size_t size,
const void *address)
: m_base(MAP_FAILED), m_size(0), m_offset(0), m_extra_offset(0), m_mode(mode)
: m_base(MAP_FAILED), m_size(0), m_offset(0), m_extra_offset(0), m_mode(mode), m_is_xsi(false)
{
mapping_handle_t map_hnd = mapping.get_mapping_handle();
if(map_hnd.is_xsi){
//Get the size
::shmid_ds xsi_ds;
int ret = ::shmctl(map_hnd.handle, IPC_STAT, &xsi_ds);
if(ret == -1){
error_info err(system_error_code());
throw interprocess_exception(err);
}
//Compare sizess
if(size == 0){
size = (std::size_t)xsi_ds.shm_segsz;
}
else if(size != (std::size_t)xsi_ds.shm_segsz){
error_info err(size_error);
throw interprocess_exception(err);
}
//Calculate flag
int flag = 0;
if(m_mode == read_only){
flag |= SHM_RDONLY;
}
else if(m_mode != read_write){
error_info err(mode_error);
throw interprocess_exception(err);
}
//Attach memory
void *base = ::shmat(map_hnd.handle, (void*)address, flag);
if(base == (void*)-1){
error_info err(system_error_code());
throw interprocess_exception(err);
}
//Update members
m_base = base;
m_offset = offset;
m_size = size;
m_mode = mode;
m_extra_offset = 0;
m_is_xsi = true;
return;
}
if(size == 0){
// offset_t filesize = lseek64
offset_t filesize = lseek
(mapping.get_mapping_handle(), offset, SEEK_END);
(map_hnd.handle, offset, SEEK_END);
if(filesize == -1 ){
error_info err(system_error_code());
throw interprocess_exception(err);
@@ -440,12 +453,13 @@ inline mapped_region::mapped_region
error_info err(size_error);
throw interprocess_exception(err);
}
filesize -= offset;
size = (size_t)filesize;
if((offset_t)size != filesize){
error_info err(size_error);
throw interprocess_exception(err);
throw interprocess_exception(err);
}
}
@@ -459,7 +473,7 @@ inline mapped_region::mapped_region
prot |= PROT_READ;
flags |= MAP_SHARED;
break;
case read_write:
prot |= (PROT_WRITE | PROT_READ);
flags |= MAP_SHARED;
@@ -469,7 +483,7 @@ inline mapped_region::mapped_region
prot |= (PROT_WRITE | PROT_READ);
flags |= MAP_PRIVATE;
break;
default:
{
error_info err(mode_error);
@@ -496,7 +510,7 @@ inline mapped_region::mapped_region
, static_cast<std::size_t>(m_extra_offset + m_size)
, prot
, flags
, mapping.get_mapping_handle()
, mapping.get_mapping_handle().handle
, offset - m_extra_offset);
//Check if mapping was successful
@@ -537,7 +551,12 @@ inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbyte
inline void mapped_region::priv_close()
{
if(m_base != MAP_FAILED){
this->flush();
if(m_is_xsi){
int ret = ::shmdt(m_base);
assert(ret == 0);
(void)ret;
return;
}
munmap(static_cast<char*>(m_base) - m_extra_offset, m_size + m_extra_offset);
m_base = MAP_FAILED;
}
@@ -546,7 +565,7 @@ inline void mapped_region::priv_close()
inline void mapped_region::dont_close_on_destruction()
{ m_base = MAP_FAILED; }
#endif //##if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#endif //##if (defined BOOST_INTERPROCESS_WINDOWS)
template<int dummy>
const std::size_t mapped_region::page_size_holder<dummy>::PageSize
@@ -560,19 +579,17 @@ inline std::size_t mapped_region::get_page_size()
return page_size_holder<0>::PageSize;
}
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void mapped_region::swap(mapped_region &other)
#else
inline void mapped_region::swap(mapped_region &&other)
#endif
{
detail::do_swap(this->m_base, other.m_base);
detail::do_swap(this->m_size, other.m_size);
detail::do_swap(this->m_offset, other.m_offset);
detail::do_swap(this->m_extra_offset, other.m_extra_offset);
detail::do_swap(this->m_mode, other.m_mode);
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
detail::do_swap(this->m_mode, other.m_mode);
#if (defined BOOST_INTERPROCESS_WINDOWS)
detail::do_swap(this->m_file_mapping_hnd, other.m_file_mapping_hnd);
#else
detail::do_swap(this->m_is_xsi, other.m_is_xsi);
#endif
}
@@ -583,13 +600,6 @@ struct null_mapped_region_function
{ return true; }
};
//!Trait class to detect if a type is
//!movable
template<>
struct is_movable<mapped_region>
{
enum { value = true };
};
/// @endcond
} //namespace interprocess {

View File

@@ -19,14 +19,17 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/allocators/allocation_type.hpp>
#include <boost/interprocess/containers/allocation_type.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/iterators.hpp>
#include <boost/interprocess/detail/math_functions.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <algorithm>
#include <utility>
#include <iterator>
//!\file
//!Implements common operations for memory algorithms.
@@ -36,206 +39,527 @@ namespace interprocess {
namespace detail {
template<class VoidPointer>
struct multi_allocation_next
class basic_multiallocation_slist
{
typedef typename detail::
pointer_to_other<VoidPointer, multi_allocation_next>::type
multi_allocation_next_ptr;
multi_allocation_next(multi_allocation_next_ptr n)
: next_(n)
{}
multi_allocation_next_ptr next_;
};
//!This iterator is returned by "allocate_many" functions so that
//!the user can access the multiple buffers allocated in a single call
template<class VoidPointer>
class basic_multiallocation_iterator
: public std::iterator<std::input_iterator_tag, char>
{
void unspecified_bool_type_func() const {}
typedef void (basic_multiallocation_iterator::*unspecified_bool_type)() const;
typedef typename detail::
pointer_to_other
<VoidPointer, multi_allocation_next<VoidPointer> >::type
multi_allocation_next_ptr;
public:
typedef char value_type;
typedef value_type & reference;
typedef value_type * pointer;
basic_multiallocation_iterator()
: next_alloc_(0)
{}
basic_multiallocation_iterator(multi_allocation_next_ptr next)
: next_alloc_(next)
{}
basic_multiallocation_iterator &operator=(const basic_multiallocation_iterator &other)
{ next_alloc_ = other.next_alloc_; return *this; }
public:
basic_multiallocation_iterator& operator++()
{ next_alloc_.next_ = detail::get_pointer(next_alloc_.next_->next_); return *this; }
basic_multiallocation_iterator operator++(int)
{
basic_multiallocation_iterator result(next_alloc_.next_);
++*this;
return result;
}
bool operator== (const basic_multiallocation_iterator& other) const
{ return next_alloc_.next_ == other.next_alloc_.next_; }
bool operator!= (const basic_multiallocation_iterator& other) const
{ return !operator== (other); }
reference operator*() const
{ return *reinterpret_cast<char*>(detail::get_pointer(next_alloc_.next_)); }
operator unspecified_bool_type() const
{ return next_alloc_.next_? &basic_multiallocation_iterator::unspecified_bool_type_func : 0; }
pointer operator->() const
{ return &(*(*this)); }
static basic_multiallocation_iterator create_simple_range(void *mem)
{
basic_multiallocation_iterator it;
typedef multi_allocation_next<VoidPointer> next_impl_t;
next_impl_t * tmp_mem = static_cast<next_impl_t*>(mem);
it = basic_multiallocation_iterator<VoidPointer>(tmp_mem);
tmp_mem->next_ = 0;
return it;
}
multi_allocation_next<VoidPointer> &get_multi_allocation_next()
{ return *next_alloc_.next_; }
typedef VoidPointer void_pointer;
private:
multi_allocation_next<VoidPointer> next_alloc_;
};
static VoidPointer &priv_get_ref(const VoidPointer &p)
{ return *static_cast<void_pointer*>(detail::get_pointer(p)); }
template<class VoidPointer>
class basic_multiallocation_chain
{
private:
basic_multiallocation_iterator<VoidPointer> it_;
VoidPointer last_mem_;
std::size_t num_mem_;
basic_multiallocation_chain(const basic_multiallocation_chain &);
basic_multiallocation_chain &operator=(const basic_multiallocation_chain &);
basic_multiallocation_slist(basic_multiallocation_slist &);
basic_multiallocation_slist &operator=(basic_multiallocation_slist &);
public:
typedef basic_multiallocation_iterator<VoidPointer> multiallocation_iterator;
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_slist)
basic_multiallocation_chain()
: it_(0), last_mem_(0), num_mem_(0)
{}
void reset()
//!This iterator is returned by "allocate_many" functions so that
//!the user can access the multiple buffers allocated in a single call
class iterator
: public std::iterator<std::input_iterator_tag, char>
{
this->it_ = multiallocation_iterator();
this->last_mem_ = 0;
this->num_mem_ = 0;
}
friend class basic_multiallocation_slist<void_pointer>;
void unspecified_bool_type_func() const {}
typedef void (iterator::*unspecified_bool_type)() const;
void push_back(void *mem)
{
typedef multi_allocation_next<VoidPointer> next_impl_t;
next_impl_t * tmp_mem = static_cast<next_impl_t*>(mem);
iterator(void_pointer node_range)
: next_node_(node_range)
{}
public:
typedef char value_type;
typedef value_type & reference;
typedef value_type * pointer;
iterator()
: next_node_(0)
{}
iterator &operator=(const iterator &other)
{ next_node_ = other.next_node_; return *this; }
public:
iterator& operator++()
{
next_node_ = *static_cast<void_pointer*>(detail::get_pointer(next_node_));
return *this;
}
if(!this->last_mem_){
this->it_ = basic_multiallocation_iterator<VoidPointer>(tmp_mem);
iterator operator++(int)
{
iterator result(*this);
++*this;
return result;
}
else{
static_cast<next_impl_t*>(detail::get_pointer(this->last_mem_))->next_ = tmp_mem;
}
tmp_mem->next_ = 0;
this->last_mem_ = tmp_mem;
++num_mem_;
}
void push_front(void *mem)
bool operator== (const iterator& other) const
{ return next_node_ == other.next_node_; }
bool operator!= (const iterator& other) const
{ return !operator== (other); }
reference operator*() const
{ return *static_cast<char*>(detail::get_pointer(next_node_)); }
operator unspecified_bool_type() const
{ return next_node_? &iterator::unspecified_bool_type_func : 0; }
pointer operator->() const
{ return &(*(*this)); }
private:
void_pointer next_node_;
};
private:
iterator it_;
public:
basic_multiallocation_slist()
: it_(iterator())
{}
basic_multiallocation_slist(void_pointer p)
: it_(p ? iterator_to(p) : iterator())
{}
basic_multiallocation_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist) other)
: it_(iterator())
{ this->swap(other); }
basic_multiallocation_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist) other)
{
typedef multi_allocation_next<VoidPointer> next_impl_t;
next_impl_t * tmp_mem = static_cast<next_impl_t*>(mem);
++num_mem_;
if(!this->last_mem_){
this->it_ = basic_multiallocation_iterator<VoidPointer>(tmp_mem);
tmp_mem->next_ = 0;
this->last_mem_ = tmp_mem;
}
else{
next_impl_t * old_first = &this->it_.get_multi_allocation_next();
tmp_mem->next_ = old_first;
this->it_ = basic_multiallocation_iterator<VoidPointer>(tmp_mem);
}
}
void swap(basic_multiallocation_chain &other_chain)
{
std::swap(this->it_, other_chain.it_);
std::swap(this->last_mem_, other_chain.last_mem_);
std::swap(this->num_mem_, other_chain.num_mem_);
}
void splice_back(basic_multiallocation_chain &other_chain)
{
typedef multi_allocation_next<VoidPointer> next_impl_t;
multiallocation_iterator end_it;
multiallocation_iterator other_it = other_chain.get_it();
multiallocation_iterator this_it = this->get_it();
if(end_it == other_it){
return;
}
else if(end_it == this_it){
this->swap(other_chain);
}
else{
static_cast<next_impl_t*>(detail::get_pointer(this->last_mem_))->next_
= &other_chain.it_.get_multi_allocation_next();
this->last_mem_ = other_chain.last_mem_;
this->num_mem_ += other_chain.num_mem_;
}
}
void *pop_front()
{
multiallocation_iterator itend;
if(this->it_ == itend){
this->last_mem_= 0;
this->num_mem_ = 0;
return 0;
}
else{
void *addr = &*it_;
++it_;
--num_mem_;
if(!num_mem_){
this->last_mem_ = 0;
this->it_ = multiallocation_iterator();
}
return addr;
}
basic_multiallocation_slist tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
bool empty() const
{ return !num_mem_; }
{ return !it_; }
multiallocation_iterator get_it() const
{ return it_; }
iterator before_begin() const
{ return iterator(void_pointer(const_cast<void*>(static_cast<const void*>(&it_.next_node_)))); }
std::size_t size() const
{ return num_mem_; }
iterator begin() const
{ return it_; }
iterator end() const
{ return iterator(); }
void clear()
{ this->it_.next_node_ = void_pointer(0); }
iterator insert_after(iterator it, void_pointer m)
{
priv_get_ref(m) = priv_get_ref(it.next_node_);
priv_get_ref(it.next_node_) = m;
return iterator(m);
}
void push_front(void_pointer m)
{
priv_get_ref(m) = this->it_.next_node_;
this->it_.next_node_ = m;
}
void pop_front()
{ ++it_; }
void *front() const
{ return detail::get_pointer(it_.next_node_); }
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
{
if (after_this != before_begin && after_this != before_end && before_begin != before_end) {
void_pointer next_b = priv_get_ref(before_begin.next_node_);
void_pointer next_e = priv_get_ref(before_end.next_node_);
void_pointer next_p = priv_get_ref(after_this.next_node_);
priv_get_ref(before_begin.next_node_) = next_e;
priv_get_ref(before_end.next_node_) = next_p;
priv_get_ref(after_this.next_node_) = next_b;
}
}
void swap(basic_multiallocation_slist &other_chain)
{
std::swap(this->it_, other_chain.it_);
}
static iterator iterator_to(void_pointer p)
{ return iterator(p); }
void_pointer extract_data()
{
void_pointer ret = empty() ? void_pointer(0) : void_pointer(&*it_);
it_ = iterator();
return ret;
}
};
template<class VoidPointer>
class basic_multiallocation_cached_slist
{
private:
basic_multiallocation_slist<VoidPointer> slist_;
typename basic_multiallocation_slist<VoidPointer>::iterator last_;
basic_multiallocation_cached_slist(basic_multiallocation_cached_slist &);
basic_multiallocation_cached_slist &operator=(basic_multiallocation_cached_slist &);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_slist)
typedef typename basic_multiallocation_slist<VoidPointer>::void_pointer void_pointer;
typedef typename basic_multiallocation_slist<VoidPointer>::iterator iterator;
basic_multiallocation_cached_slist()
: slist_(), last_(slist_.before_begin())
{}
/*
basic_multiallocation_cached_slist(iterator first_node)
: slist_(first_node), last_(slist_.before_begin())
{
iterator end;
while(first_node != end){
++last_;
}
}*/
basic_multiallocation_cached_slist(void_pointer p1, void_pointer p2)
: slist_(p1), last_(p2 ? iterator_to(p2) : slist_.before_begin())
{}
basic_multiallocation_cached_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist) other)
: slist_(), last_(slist_.before_begin())
{ this->swap(other); }
basic_multiallocation_cached_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist) other)
{
basic_multiallocation_cached_slist tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
bool empty() const
{ return slist_.empty(); }
iterator before_begin() const
{ return slist_.before_begin(); }
iterator begin() const
{ return slist_.begin(); }
iterator end() const
{ return slist_.end(); }
iterator last() const
{ return last_; }
void clear()
{
slist_.clear();
last_ = slist_.before_begin();
}
iterator insert_after(iterator it, void_pointer m)
{
slist_.insert_after(it, m);
if(it == last_){
last_ = slist_.iterator_to(m);
}
return iterator_to(m);
}
void push_front(void_pointer m)
{ this->insert_after(this->before_begin(), m); }
void push_back(void_pointer m)
{ this->insert_after(last_, m); }
void pop_front()
{
if(last_ == slist_.begin()){
last_ = slist_.before_begin();
}
slist_.pop_front();
}
void *front() const
{ return slist_.front(); }
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
{
if(before_begin == before_end)
return;
if(after_this == last_){
last_ = before_end;
}
slist_.splice_after(after_this, before_begin, before_end);
}
void swap(basic_multiallocation_cached_slist &x)
{
slist_.swap(x.slist_);
using std::swap;
swap(last_, x.last_);
if(last_ == x.before_begin()){
last_ = this->before_begin();
}
if(x.last_ == this->before_begin()){
x.last_ = x.before_begin();
}
}
static iterator iterator_to(void_pointer p)
{ return basic_multiallocation_slist<VoidPointer>::iterator_to(p); }
std::pair<void_pointer, void_pointer> extract_data()
{
if(this->empty()){
return std::pair<void_pointer, void_pointer>(void_pointer(0), void_pointer(0));
}
else{
void_pointer p1 = slist_.extract_data();
void_pointer p2 = void_pointer(&*last_);
last_ = iterator();
return std::pair<void_pointer, void_pointer>(p1, p2);
}
}
};
template<class MultiallocatorCachedSlist>
class basic_multiallocation_cached_counted_slist
{
private:
MultiallocatorCachedSlist cached_slist_;
std::size_t size_;
basic_multiallocation_cached_counted_slist(basic_multiallocation_cached_counted_slist &);
basic_multiallocation_cached_counted_slist &operator=(basic_multiallocation_cached_counted_slist &);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_counted_slist)
typedef typename MultiallocatorCachedSlist::void_pointer void_pointer;
typedef typename MultiallocatorCachedSlist::iterator iterator;
basic_multiallocation_cached_counted_slist()
: cached_slist_(), size_(0)
{}
basic_multiallocation_cached_counted_slist(void_pointer p1, void_pointer p2, std::size_t n)
: cached_slist_(p1, p2), size_(n)
{}
basic_multiallocation_cached_counted_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist) other)
: cached_slist_(), size_(0)
{ this->swap(other); }
basic_multiallocation_cached_counted_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist) other)
{
basic_multiallocation_cached_counted_slist tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
basic_multiallocation_cached_counted_slist (MultiallocatorCachedSlist mem, std::size_t n)
: cached_slist_(boost::interprocess::move(mem)), size_(n)
{}
bool empty() const
{ return cached_slist_.empty(); }
std::size_t size() const
{ return size_; }
iterator before_begin() const
{ return cached_slist_.before_begin(); }
iterator begin() const
{ return cached_slist_.begin(); }
iterator end() const
{ return cached_slist_.end(); }
iterator last() const
{ return cached_slist_.last(); }
void clear()
{
cached_slist_.clear();
size_ = 0;
}
iterator insert_after(iterator it, void_pointer m)
{
iterator ret = cached_slist_.insert_after(it, m);
++size_;
return ret;
}
void push_front(void_pointer m)
{ this->insert_after(this->before_begin(), m); }
void push_back(void_pointer m)
{ this->insert_after(this->before_begin(), m); }
void pop_front()
{
cached_slist_.pop_front();
--size_;
}
void *front() const
{ return cached_slist_.front(); }
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x, iterator before_begin, iterator before_end)
{
std::size_t n = static_cast<std::size_t>(std::distance(before_begin, before_end));
this->splice_after(after_this, x, before_begin, before_end, n);
}
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x, iterator before_begin, iterator before_end, std::size_t n)
{
cached_slist_.splice_after(after_this, before_begin, before_end);
size_ += n;
x.size_ -= n;
}
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x)
{
cached_slist_.splice_after(after_this, x.before_begin(), x.last());
size_ += x.size_;
x.size_ = 0;
}
void swap(basic_multiallocation_cached_counted_slist &x)
{
cached_slist_.swap(x.cached_slist_);
using std::swap;
swap(size_, x.size_);
}
static iterator iterator_to(void_pointer p)
{ return MultiallocatorCachedSlist::iterator_to(p); }
std::pair<void_pointer, void_pointer> extract_data()
{
size_ = 0;
return cached_slist_.extract_data();
}
};
template<class T>
struct cast_functor
{
typedef typename detail::add_reference<T>::type result_type;
result_type operator()(char &ptr) const
{ return *static_cast<T*>(static_cast<void*>(&ptr)); }
};
template<class MultiallocationChain, class T>
class transform_multiallocation_chain
{
private:
MultiallocationChain holder_;
typedef typename MultiallocationChain::void_pointer void_pointer;
typedef typename boost::pointer_to_other
<void_pointer, T>::type pointer;
transform_multiallocation_chain(transform_multiallocation_chain &);
transform_multiallocation_chain &operator=(transform_multiallocation_chain &);
static pointer cast(void_pointer p)
{
return pointer(static_cast<T*>(detail::get_pointer(p)));
}
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(transform_multiallocation_chain)
typedef transform_iterator
< typename MultiallocationChain::iterator
, detail::cast_functor <T> > iterator;
transform_multiallocation_chain(void_pointer p1, void_pointer p2, std::size_t n)
: holder_(p1, p2, n)
{}
transform_multiallocation_chain()
: holder_()
{}
transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain) other)
: holder_()
{ this->swap(other); }
transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(MultiallocationChain) other)
: holder_(boost::interprocess::move(other))
{}
transform_multiallocation_chain& operator=(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain) other)
{
transform_multiallocation_chain tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
void push_front(pointer mem)
{ holder_.push_front(mem); }
void swap(transform_multiallocation_chain &other_chain)
{ holder_.swap(other_chain.holder_); }
/*
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
{ holder_.splice_after(after_this.base(), before_begin.base(), before_end.base()); }
*/
void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_begin, iterator before_end, std::size_t n)
{ holder_.splice_after(after_this.base(), x.holder_, before_begin.base(), before_end.base(), n); }
void pop_front()
{ holder_.pop_front(); }
pointer front() const
{ return cast(holder_.front()); }
bool empty() const
{ return holder_.empty(); }
iterator before_begin() const
{ return iterator(holder_.before_begin()); }
iterator begin() const
{ return iterator(holder_.begin()); }
iterator end() const
{ return iterator(holder_.end()); }
iterator last() const
{ return iterator(holder_.last()); }
std::size_t size() const
{ return holder_.size(); }
void clear()
{ holder_.clear(); }
iterator insert_after(iterator it, pointer m)
{ return iterator(holder_.insert_after(it.base(), m)); }
static iterator iterator_to(pointer p)
{ return iterator(MultiallocationChain::iterator_to(p)); }
std::pair<void_pointer, void_pointer> extract_data()
{ return holder_.extract_data(); }
MultiallocationChain extract_multiallocation_chain()
{
return MultiallocationChain(boost::interprocess::move(holder_));
}
};
//!This class implements several allocation functions shared by different algorithms
//!(aligned allocation, multiple allocation...).
@@ -245,19 +569,16 @@ class memory_algorithm_common
public:
typedef typename MemoryAlgorithm::void_pointer void_pointer;
typedef typename MemoryAlgorithm::block_ctrl block_ctrl;
typedef typename MemoryAlgorithm::multiallocation_iterator multiallocation_iterator;
typedef multi_allocation_next<void_pointer> multi_allocation_next_t;
typedef typename multi_allocation_next_t::
multi_allocation_next_ptr multi_allocation_next_ptr;
typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain;
typedef memory_algorithm_common<MemoryAlgorithm> this_type;
static const std::size_t Alignment = MemoryAlgorithm::Alignment;
static const std::size_t MinBlockUnits = MemoryAlgorithm::MinBlockUnits;
static const std::size_t AllocatedCtrlBytes = MemoryAlgorithm::AllocatedCtrlBytes;
static const std::size_t AllocatedCtrlUnits = MemoryAlgorithm::AllocatedCtrlUnits;
static const std::size_t BlockCtrlBytes = MemoryAlgorithm::BlockCtrlBytes;
static const std::size_t BlockCtrlUnits = MemoryAlgorithm::BlockCtrlUnits;
static const std::size_t UsableByPreviousChunk = MemoryAlgorithm::UsableByPreviousChunk;
static const std::size_t Alignment = MemoryAlgorithm::Alignment;
static const std::size_t MinBlockUnits = MemoryAlgorithm::MinBlockUnits;
static const std::size_t AllocatedCtrlBytes = MemoryAlgorithm::AllocatedCtrlBytes;
static const std::size_t AllocatedCtrlUnits = MemoryAlgorithm::AllocatedCtrlUnits;
static const std::size_t BlockCtrlBytes = MemoryAlgorithm::BlockCtrlBytes;
static const std::size_t BlockCtrlUnits = MemoryAlgorithm::BlockCtrlUnits;
static const std::size_t UsableByPreviousChunk = MemoryAlgorithm::UsableByPreviousChunk;
static void assert_alignment(const void *ptr)
{ assert_alignment((std::size_t)ptr); }
@@ -280,12 +601,17 @@ class memory_algorithm_common
static std::size_t multiple_of_units(std::size_t size)
{ return detail::get_rounded_size(size, Alignment); }
static multiallocation_iterator allocate_many
static multiallocation_chain allocate_many
(MemoryAlgorithm *memory_algo, std::size_t elem_bytes, std::size_t n_elements)
{
return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, 0);
}
static void deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain chain)
{
return this_type::priv_deallocate_many(memory_algo, boost::interprocess::move(chain));
}
static bool calculate_lcm_and_needs_backwards_lcmed
(std::size_t backwards_multiple, std::size_t received_size, std::size_t size_to_achieve,
std::size_t &lcm_out, std::size_t &needs_backwards_lcmed_out)
@@ -381,7 +707,7 @@ class memory_algorithm_common
return true;
}
static multiallocation_iterator allocate_many
static multiallocation_chain allocate_many
( MemoryAlgorithm *memory_algo
, const std::size_t *elem_sizes
, std::size_t n_elements
@@ -403,7 +729,8 @@ class memory_algorithm_common
std::size_t real_size;
if(alignment <= Alignment){
return memory_algo->priv_allocate(allocate_new, nbytes, nbytes, real_size).first;
return memory_algo->priv_allocate
(boost::interprocess::allocate_new, nbytes, nbytes, real_size).first;
}
if(nbytes > UsableByPreviousChunk)
@@ -428,7 +755,8 @@ class memory_algorithm_common
);
//Now allocate the buffer
void *buffer = memory_algo->priv_allocate(allocate_new, request, request, real_size).first;
void *buffer = memory_algo->priv_allocate
(boost::interprocess::allocate_new, request, request, real_size).first;
if(!buffer){
return 0;
}
@@ -608,7 +936,7 @@ class memory_algorithm_common
}
private:
static multiallocation_iterator priv_allocate_many
static multiallocation_chain priv_allocate_many
( MemoryAlgorithm *memory_algo
, const std::size_t *elem_sizes
, std::size_t n_elements
@@ -620,7 +948,7 @@ class memory_algorithm_common
//Calculate the total size of all requests
std::size_t total_request_units = 0;
std::size_t elem_units = 0;
const std::size_t ptr_size_units = memory_algo->priv_get_total_units(sizeof(multi_allocation_next_ptr));
const std::size_t ptr_size_units = memory_algo->priv_get_total_units(sizeof(void_pointer));
if(!sizeof_element){
elem_units = memory_algo->priv_get_total_units(*elem_sizes);
elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units;
@@ -634,7 +962,8 @@ class memory_algorithm_common
}
}
multi_allocation_next_ptr first = 0, previous = 0;
multiallocation_chain chain;
std::size_t low_idx = 0;
while(low_idx < n_elements){
std::size_t total_bytes = total_request_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk;
@@ -645,7 +974,7 @@ class memory_algorithm_common
std::size_t received_size;
std::pair<void *, bool> ret = memory_algo->priv_allocate
(allocate_new, min_allocation, total_bytes, received_size, 0);
(boost::interprocess::allocate_new, min_allocation, total_bytes, received_size, 0);
if(!ret.first){
break;
}
@@ -710,33 +1039,28 @@ class memory_algorithm_common
block_address += new_block->m_size*Alignment;
total_used_units += new_block->m_size;
//Check we have enough room to overwrite the intrusive pointer
assert((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(multi_allocation_next_t));
multi_allocation_next_ptr p = new(memory_algo->priv_get_user_buffer(new_block))multi_allocation_next_t(0);
if(!first){
first = p;
}
else{
previous->next_ = p;
}
previous = p;
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;
}
//Sanity check
BOOST_ASSERT(total_used_units == received_units);
}
if(low_idx != n_elements){
while(first){
multi_allocation_next_ptr prev = first;
first = first->next_;
memory_algo->priv_deallocate(detail::get_pointer(prev));
}
return multiallocation_iterator();
priv_deallocate_many(memory_algo, boost::interprocess::move(chain));
}
else{
return multiallocation_iterator(first);
return boost::interprocess::move(chain);
}
static void priv_deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain chain)
{
while(!chain.empty()){
void *addr = detail::get_pointer(chain.front());
chain.pop_front();
memory_algo->priv_deallocate(addr);
}
}
};

View File

@@ -18,8 +18,10 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/allocators/allocation_type.hpp>
#include <boost/interprocess/containers/allocation_type.hpp>
#include <boost/interprocess/offset_ptr.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -67,7 +69,7 @@ class simple_seq_fit_impl
private:
struct block_ctrl;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, block_ctrl>::type block_ctrl_ptr;
/*!Block control structure*/
@@ -149,7 +151,7 @@ class simple_seq_fit_impl
void clear_free_memory();
std::pair<void *, bool>
allocation_command (allocation_type command, std::size_t limit_size,
allocation_command (boost::interprocess::allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
void *reuse_ptr = 0, std::size_t backwards_multiple = 1);
@@ -169,7 +171,7 @@ class simple_seq_fit_impl
private:
/*!Real allocation algorithm with min allocation option*/
std::pair<void *, bool> priv_allocate(allocation_type command
std::pair<void *, bool> priv_allocate(boost::interprocess::allocation_type command
,std::size_t min_size
,std::size_t preferred_size
,std::size_t &received_size
@@ -188,7 +190,7 @@ class simple_seq_fit_impl
,std::size_t &received_size);
/*!Real expand to both sides implementation*/
void* priv_expand_both_sides(allocation_type command
void* priv_expand_both_sides(boost::interprocess::allocation_type command
,std::size_t min_size
,std::size_t preferred_size
,std::size_t &received_size
@@ -375,7 +377,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
std::size_t ignore;
return priv_allocate(allocate_new, nbytes, nbytes, ignore).first;
return priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first;
}
template<class MutexFamily, class VoidPointer>
@@ -390,7 +392,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 (allocation_type command, std::size_t min_size,
allocation_command (boost::interprocess::allocation_type command, std::size_t min_size,
std::size_t preferred_size,std::size_t &received_size,
void *reuse_ptr, std::size_t backwards_multiple)
{
@@ -398,7 +400,7 @@ inline std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
(void)backwards_multiple;
command &= ~expand_bwd;
command &= ~boost::interprocess::expand_bwd;
if(!command)
return std::pair<void *, bool>(0, false);
return priv_allocate(command, min_size, preferred_size, received_size, reuse_ptr);
@@ -426,7 +428,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
//Multisegment pointer. Let's try first the normal allocation
//since it's faster.
std::size_t ignore;
void *addr = this->priv_allocate(allocate_new, nbytes, nbytes, ignore).first;
void *addr = this->priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first;
if(!addr){
//If this fails we will try the allocation through the segment
//creator.
@@ -447,7 +449,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
p_services->create_new_segment(MinBlockSize > nbytes ? MinBlockSize : nbytes);
if(ret.first){
priv_add_segment(ret.first, ret.second);
addr = this->priv_allocate(allocate_new, nbytes, nbytes, ignore).first;
addr = this->priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first;
}
}
return addr;
@@ -455,7 +457,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
priv_expand_both_sides(allocation_type command
priv_expand_both_sides(boost::interprocess::allocation_type command
,std::size_t min_size
,std::size_t preferred_size
,std::size_t &received_size
@@ -471,14 +473,14 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
return reuse_ptr;
}
if(command & expand_fwd){
if(command & boost::interprocess::expand_fwd){
if(priv_expand(reuse_ptr, min_size, preferred_size, received_size))
return reuse_ptr;
}
else{
received_size = this->size(reuse_ptr);
}
if(command & expand_bwd){
if(command & boost::interprocess::expand_bwd){
std::size_t extra_forward = !received_size ? 0 : received_size + BlockCtrlBytes;
prev_block_t prev_pair = priv_prev_block_if_free(reuse);
block_ctrl *prev = prev_pair.second;
@@ -534,13 +536,13 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
priv_allocate(allocation_type command
priv_allocate(boost::interprocess::allocation_type command
,std::size_t limit_size
,std::size_t preferred_size
,std::size_t &received_size
,void *reuse_ptr)
{
if(command & shrink_in_place){
if(command & boost::interprocess::shrink_in_place){
bool success =
this->priv_shrink(reuse_ptr, limit_size, preferred_size, received_size);
return std::pair<void *, bool> ((success ? reuse_ptr : 0), true);
@@ -565,14 +567,14 @@ std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
//Expand in place
//reuse_ptr, limit_size, preferred_size, received_size
//
if(reuse_ptr && (command & (expand_fwd | expand_bwd))){
if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){
void *ret = priv_expand_both_sides
(command, limit_size, preferred_size, received_size, reuse_ptr, true);
if(ret)
return return_type(ret, true);
}
if(command & allocate_new){
if(command & boost::interprocess::allocate_new){
received_size = 0;
while(block != root){
//Update biggest block pointers
@@ -600,7 +602,7 @@ std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
}
}
//Now try to expand both sides with min size
if(reuse_ptr && (command & (expand_fwd | expand_bwd))){
if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){
return return_type(priv_expand_both_sides
(command, limit_size, preferred_size, received_size, reuse_ptr, false), true);
}
@@ -809,12 +811,12 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
std::size_t ignore;
if(alignment <= Alignment){
return priv_allocate(allocate_new, nbytes, nbytes, ignore).first;
return priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first;
}
std::size_t request =
nbytes + alignment + MinBlockSize*Alignment - BlockCtrlBytes;
void *buffer = priv_allocate(allocate_new, request, request, ignore).first;
void *buffer = priv_allocate(boost::interprocess::allocate_new, request, request, ignore).first;
if(!buffer)
return 0;
else if ((((std::size_t)(buffer)) % alignment) == 0)

View File

@@ -18,8 +18,10 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/allocators/allocation_type.hpp>
#include <boost/interprocess/containers/allocation_type.hpp>
#include <boost/interprocess/offset_ptr.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -61,15 +63,13 @@ class simple_seq_fit_impl
typedef MutexFamily mutex_family;
//!Pointer type to be used with the rest of the Interprocess framework
typedef VoidPointer void_pointer;
typedef detail::basic_multiallocation_iterator
<void_pointer> multiallocation_iterator;
typedef detail::basic_multiallocation_chain
<void_pointer> multiallocation_chain;
typedef detail::basic_multiallocation_cached_slist<void_pointer> multialloc_cached;
typedef detail::basic_multiallocation_cached_counted_slist
<multialloc_cached> multiallocation_chain;
private:
class block_ctrl;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, block_ctrl>::type block_ctrl_ptr;
class block_ctrl;
@@ -109,7 +109,6 @@ class simple_seq_fit_impl
std::size_t m_extra_hdr_bytes;
} m_header;
friend class detail::basic_multiallocation_iterator<void_pointer>;
friend class detail::memory_algorithm_common<simple_seq_fit_impl>;
typedef detail::memory_algorithm_common<simple_seq_fit_impl> algo_impl_t;
@@ -134,13 +133,27 @@ class simple_seq_fit_impl
/// @cond
//!Multiple element allocation, same size
multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements);
multiallocation_chain
allocate_many(std::size_t elem_bytes, std::size_t num_elements)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
return algo_impl_t::allocate_many(this, elem_bytes, num_elements);
}
//!Multiple element allocation, different size
multiallocation_iterator allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element);
multiallocation_chain
allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
return algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element);
}
//!Multiple element deallocation
void deallocate_many(multiallocation_iterator it);
void deallocate_many(multiallocation_chain chain);
/// @endcond
@@ -171,12 +184,12 @@ class simple_seq_fit_impl
template<class T>
std::pair<T *, bool>
allocation_command (allocation_type command, std::size_t limit_size,
allocation_command (boost::interprocess::allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
T *reuse_ptr = 0);
std::pair<void *, bool>
raw_allocation_command (allocation_type command, std::size_t limit_size,
raw_allocation_command (boost::interprocess::allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
void *reuse_ptr = 0, std::size_t sizeof_object = 1);
@@ -196,13 +209,13 @@ class simple_seq_fit_impl
static block_ctrl *priv_get_block(const void *ptr);
//!Real allocation algorithm with min allocation option
std::pair<void *, bool> priv_allocate(allocation_type command
std::pair<void *, bool> priv_allocate(boost::interprocess::allocation_type command
,std::size_t min_size
,std::size_t preferred_size
,std::size_t &received_size
,void *reuse_ptr = 0);
std::pair<void *, bool> priv_allocation_command(allocation_type command
std::pair<void *, bool> priv_allocation_command(boost::interprocess::allocation_type command
,std::size_t min_size
,std::size_t preferred_size
,std::size_t &received_size
@@ -233,7 +246,7 @@ class simple_seq_fit_impl
,std::size_t &received_size);
//!Real expand to both sides implementation
void* priv_expand_both_sides(allocation_type command
void* priv_expand_both_sides(boost::interprocess::allocation_type command
,std::size_t min_size
,std::size_t preferred_size
,std::size_t &received_size
@@ -386,7 +399,7 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::shrink_to_fit()
if(!m_header.m_allocated){
assert(prev == root);
std::size_t ignore;
unique_block = priv_allocate(allocate_new, 0, 0, ignore).first;
unique_block = priv_allocate(boost::interprocess::allocate_new, 0, 0, ignore).first;
if(!unique_block)
return;
last = detail::get_pointer(m_header.m_root.m_next);
@@ -547,7 +560,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
std::size_t ignore;
return priv_allocate(allocate_new, nbytes, nbytes, ignore).first;
return priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first;
}
template<class MutexFamily, class VoidPointer>
@@ -564,7 +577,7 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
template<class T>
inline std::pair<T*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
allocation_command (allocation_type command, std::size_t limit_size,
allocation_command (boost::interprocess::allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
T *reuse_ptr)
{
@@ -577,13 +590,13 @@ inline std::pair<T*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
inline std::pair<void*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
raw_allocation_command (allocation_type command, std::size_t limit_objects,
raw_allocation_command (boost::interprocess::allocation_type command, std::size_t limit_objects,
std::size_t preferred_objects,std::size_t &received_objects,
void *reuse_ptr, std::size_t sizeof_object)
{
if(!sizeof_object)
return std::pair<void *, bool>(static_cast<void*>(0), 0);
if(command & try_shrink_in_place){
if(command & boost::interprocess::try_shrink_in_place){
bool success = algo_impl_t::try_shrink
( this, reuse_ptr, limit_objects*sizeof_object
, preferred_objects*sizeof_object, received_objects);
@@ -596,11 +609,11 @@ inline std::pair<void*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
inline std::pair<void*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
priv_allocation_command (allocation_type command, std::size_t limit_size,
priv_allocation_command (boost::interprocess::allocation_type command, std::size_t limit_size,
std::size_t preferred_size, std::size_t &received_size,
void *reuse_ptr, std::size_t sizeof_object)
{
command &= ~expand_bwd;
command &= ~boost::interprocess::expand_bwd;
if(!command) return std::pair<void *, bool>(static_cast<void*>(0), false);
std::pair<void*, bool> ret;
@@ -634,7 +647,7 @@ inline std::size_t simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
priv_expand_both_sides(allocation_type command
priv_expand_both_sides(boost::interprocess::allocation_type command
,std::size_t min_size
,std::size_t preferred_size
,std::size_t &received_size
@@ -650,14 +663,14 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
return reuse_ptr;
}
if(command & expand_fwd){
if(command & boost::interprocess::expand_fwd){
if(priv_expand(reuse_ptr, min_size, preferred_size, received_size))
return reuse_ptr;
}
else{
received_size = this->size(reuse_ptr);
}
if(command & expand_bwd){
if(command & boost::interprocess::expand_bwd){
std::size_t extra_forward = !received_size ? 0 : received_size + BlockCtrlBytes;
prev_block_t prev_pair = priv_prev_block_if_free(reuse);
block_ctrl *prev = prev_pair.second;
@@ -711,43 +724,20 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
return 0;
}
template<class MutexFamily, class VoidPointer>
inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::multiallocation_iterator
simple_seq_fit_impl<MutexFamily, VoidPointer>::
allocate_many(std::size_t elem_bytes, std::size_t num_elements)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
return algo_impl_t::
allocate_many(this, elem_bytes, num_elements);
}
template<class MutexFamily, class VoidPointer>
inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::
deallocate_many(typename simple_seq_fit_impl<MutexFamily, VoidPointer>::multiallocation_iterator it)
deallocate_many(typename simple_seq_fit_impl<MutexFamily, VoidPointer>::multiallocation_chain chain)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
while(it){
void *addr = &*it;
++it;
while(!chain.empty()){
void *addr = chain.front();
chain.pop_front();
this->priv_deallocate(addr);
}
}
template<class MutexFamily, class VoidPointer>
inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::multiallocation_iterator
simple_seq_fit_impl<MutexFamily, VoidPointer>::
allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
return algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element);
}
template<class MutexFamily, class VoidPointer>
inline std::size_t simple_seq_fit_impl<MutexFamily, VoidPointer>::
priv_get_total_units(std::size_t userbytes)
@@ -759,13 +749,13 @@ inline std::size_t simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer>
std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
priv_allocate(allocation_type command
priv_allocate(boost::interprocess::allocation_type command
,std::size_t limit_size
,std::size_t preferred_size
,std::size_t &received_size
,void *reuse_ptr)
{
if(command & shrink_in_place){
if(command & boost::interprocess::shrink_in_place){
bool success =
algo_impl_t::shrink(this, reuse_ptr, limit_size, preferred_size, received_size);
return std::pair<void *, bool> ((success ? reuse_ptr : 0), true);
@@ -790,7 +780,7 @@ std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
//Expand in place
//reuse_ptr, limit_size, preferred_size, received_size
//
if(reuse_ptr && (command & (expand_fwd | expand_bwd))){
if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){
void *ret = priv_expand_both_sides
(command, limit_size, preferred_size, received_size, reuse_ptr, true);
if(ret){
@@ -799,7 +789,7 @@ std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
}
}
if(command & allocate_new){
if(command & boost::interprocess::allocate_new){
received_size = 0;
while(block != root){
//Update biggest block pointers
@@ -835,7 +825,7 @@ std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::
}
}
//Now try to expand both sides with min size
if(reuse_ptr && (command & (expand_fwd | expand_bwd))){
if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){
return_type ret (priv_expand_both_sides
(command, limit_size, preferred_size, received_size, reuse_ptr, false), true);
algo_impl_t::assert_alignment(ret.first);

View File

@@ -18,9 +18,11 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
#include <boost/interprocess/allocators/allocation_type.hpp>
#include <boost/interprocess/containers/allocation_type.hpp>
#include <boost/interprocess/offset_ptr.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -40,15 +42,7 @@
#include <cassert>
#include <new>
//#define BOOST_INTERPROCESS_RBTREE_BEST_FIT_USE_SPLAY
#ifndef BOOST_INTERPROCESS_RBTREE_BEST_FIT_USE_SPLAY
#include <boost/intrusive/set.hpp>
#else
//#include <boost/intrusive/splay_set.hpp>
//#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/sg_set.hpp>
#endif
//!\file
//!Describes a best-fit algorithm based in an intrusive red-black tree used to allocate
@@ -75,35 +69,26 @@ class rbtree_best_fit
typedef MutexFamily mutex_family;
//!Pointer type to be used with the rest of the Interprocess framework
typedef VoidPointer void_pointer;
typedef detail::basic_multiallocation_iterator
<void_pointer> multiallocation_iterator;
typedef detail::basic_multiallocation_chain
<void_pointer> multiallocation_chain;
//typedef detail::basic_multiallocation_cached_counted_slist<void_pointer> multiallocation_chain;
typedef detail::basic_multiallocation_cached_slist<void_pointer> multialloc_cached;
typedef detail::basic_multiallocation_cached_counted_slist
<multialloc_cached> multiallocation_chain;
/// @cond
private:
struct block_ctrl;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, block_ctrl>::type block_ctrl_ptr;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, char>::type char_ptr;
#ifndef BOOST_INTERPROCESS_RBTREE_BEST_FIT_USE_SPLAY
typedef typename bi::make_set_base_hook
#else
// typedef typename bi::make_splay_set_base_hook
// typedef typename bi::make_avl_set_base_hook
typedef typename bi::make_sg_set_base_hook
#endif
< bi::void_pointer<VoidPointer>
, bi::optimize_size<true>
, bi::link_mode<bi::normal_link> >::type TreeHook;
typedef detail::multi_allocation_next<void_pointer> multi_allocation_next_t;
typedef typename multi_allocation_next_t::
multi_allocation_next_ptr multi_allocation_next_ptr;
struct SizeHolder
{
//!This block's memory size (including block_ctrl
@@ -138,13 +123,7 @@ class rbtree_best_fit
//!Shared interprocess_mutex to protect memory allocate/deallocate
typedef typename MutexFamily::mutex_type interprocess_mutex;
#ifndef BOOST_INTERPROCESS_RBTREE_BEST_FIT_USE_SPLAY
typedef typename bi::make_multiset
#else
//typedef typename bi::make_splay_multiset
//typedef typename bi::make_avl_multiset
typedef typename bi::make_sg_multiset
#endif
<block_ctrl, bi::base_hook<TreeHook> >::type Imultiset;
typedef typename Imultiset::iterator imultiset_iterator;
@@ -163,7 +142,6 @@ class rbtree_best_fit
std::size_t m_size;
} m_header;
friend class detail::basic_multiallocation_iterator<void_pointer>;
friend class detail::memory_algorithm_common<rbtree_best_fit>;
typedef detail::memory_algorithm_common<rbtree_best_fit> algo_impl_t;
@@ -192,13 +170,27 @@ class rbtree_best_fit
//Experimental. Dont' use
//!Multiple element allocation, same size
multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements);
multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t num_elements)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
return algo_impl_t::allocate_many(this, elem_bytes, num_elements);
}
//!Multiple element allocation, different size
multiallocation_iterator allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element);
multiallocation_chain allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
return algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element);
}
//!Multiple element allocation, different size
void deallocate_many(multiallocation_iterator it);
void deallocate_many(multiallocation_chain chain);
/// @endcond
@@ -231,12 +223,12 @@ class rbtree_best_fit
template<class T>
std::pair<T *, bool>
allocation_command (allocation_type command, std::size_t limit_size,
allocation_command (boost::interprocess::allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
T *reuse_ptr = 0);
std::pair<void *, bool>
raw_allocation_command (allocation_type command, std::size_t limit_object,
raw_allocation_command (boost::interprocess::allocation_type command, std::size_t limit_object,
std::size_t preferred_object,std::size_t &received_object,
void *reuse_ptr = 0, std::size_t sizeof_object = 1);
@@ -252,13 +244,13 @@ class rbtree_best_fit
static std::size_t priv_first_block_offset(const void *this_ptr, std::size_t extra_hdr_bytes);
std::pair<void*, bool>
priv_allocation_command(allocation_type command, std::size_t limit_size,
priv_allocation_command(boost::interprocess::allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
void *reuse_ptr, std::size_t sizeof_object);
//!Real allocation algorithm with min allocation option
std::pair<void *, bool> priv_allocate(allocation_type command
std::pair<void *, bool> priv_allocate(boost::interprocess::allocation_type command
,std::size_t limit_size
,std::size_t preferred_size
,std::size_t &received_size
@@ -281,7 +273,7 @@ class rbtree_best_fit
,std::size_t &received_size);
//!Real expand to both sides implementation
void* priv_expand_both_sides(allocation_type command
void* priv_expand_both_sides(boost::interprocess::allocation_type command
,std::size_t min_size
,std::size_t preferred_size
,std::size_t &received_size
@@ -463,7 +455,7 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::shrink_to_fit()
block_ctrl *last_block;
if(priv_next_block(first_block) == old_end_block){
std::size_t ignore;
unique_buffer = priv_allocate(allocate_new, 0, 0, ignore).first;
unique_buffer = priv_allocate(boost::interprocess::allocate_new, 0, 0, ignore).first;
if(!unique_buffer)
return;
algo_impl_t::assert_alignment(unique_buffer);
@@ -631,7 +623,7 @@ inline void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
std::size_t ignore;
void * ret = priv_allocate(allocate_new, nbytes, nbytes, ignore).first;
void * ret = priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first;
return ret;
}
@@ -648,7 +640,7 @@ inline void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
template<class T>
inline std::pair<T*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
allocation_command (allocation_type command, std::size_t limit_size,
allocation_command (boost::interprocess::allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
T *reuse_ptr)
{
@@ -661,13 +653,13 @@ inline std::pair<T*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignmen
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
inline std::pair<void*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
raw_allocation_command (allocation_type command, std::size_t limit_objects,
raw_allocation_command (boost::interprocess::allocation_type command, std::size_t limit_objects,
std::size_t preferred_objects,std::size_t &received_objects,
void *reuse_ptr, std::size_t sizeof_object)
{
if(!sizeof_object)
return std::pair<void *, bool>(static_cast<void*>(0), 0);
if(command & try_shrink_in_place){
if(command & boost::interprocess::try_shrink_in_place){
bool success = algo_impl_t::try_shrink
( this, reuse_ptr, limit_objects*sizeof_object
, preferred_objects*sizeof_object, received_objects);
@@ -681,7 +673,7 @@ inline std::pair<void*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlign
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
inline std::pair<void*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
priv_allocation_command (allocation_type command, std::size_t limit_size,
priv_allocation_command (boost::interprocess::allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
void *reuse_ptr, std::size_t sizeof_object)
{
@@ -732,7 +724,7 @@ inline void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::zero_free_m
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
priv_expand_both_sides(allocation_type command
priv_expand_both_sides(boost::interprocess::allocation_type command
,std::size_t min_size
,std::size_t preferred_size
,std::size_t &received_size
@@ -741,7 +733,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
,std::size_t backwards_multiple)
{
algo_impl_t::assert_alignment(reuse_ptr);
if(command & expand_fwd){
if(command & boost::interprocess::expand_fwd){
if(priv_expand(reuse_ptr, min_size, preferred_size, received_size))
return reuse_ptr;
}
@@ -756,7 +748,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
BOOST_ASSERT(0 == (preferred_size % backwards_multiple));
}
if(command & expand_bwd){
if(command & boost::interprocess::expand_bwd){
//Obtain the real size of the block
block_ctrl *reuse = priv_get_block(reuse_ptr);
@@ -791,7 +783,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
//Check if previous block has enough size
if(std::size_t(prev_block->m_size*Alignment) >= needs_backwards_aligned){
//Now take all next space. This will succeed
if(command & expand_fwd){
if(command & boost::interprocess::expand_fwd){
std::size_t received_size2;
if(!priv_expand(reuse_ptr, received_size, received_size, received_size2)){
assert(0);
@@ -873,45 +865,19 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
return 0;
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::multiallocation_iterator
rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
allocate_many(std::size_t elem_bytes, std::size_t num_elements)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
return algo_impl_t::allocate_many(this, elem_bytes, num_elements);
}
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_iterator it)
deallocate_many(typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::multiallocation_chain chain)
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//-----------------------
while(it){
void *addr = &*it;
++it;
this->priv_deallocate(addr);
}
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::multiallocation_iterator
rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element)
{
//-----------------------
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::deallocate_many(this, boost::interprocess::move(chain));
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
std::pair<void *, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
priv_allocate(allocation_type command
priv_allocate(boost::interprocess::allocation_type command
,std::size_t limit_size
,std::size_t preferred_size
,std::size_t &received_size
@@ -919,9 +885,9 @@ std::pair<void *, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:
,std::size_t backwards_multiple)
{
//Remove me. Forbid backwards allocation
//command &= (~expand_bwd);
//command &= (~boost::interprocess::expand_bwd);
if(command & shrink_in_place){
if(command & boost::interprocess::shrink_in_place){
bool success =
algo_impl_t::shrink(this, reuse_ptr, limit_size, preferred_size, received_size);
return std::pair<void *, bool> ((success ? reuse_ptr : 0), true);
@@ -940,14 +906,14 @@ std::pair<void *, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:
std::size_t limit_units = priv_get_total_units(limit_size);
//Expand in place
if(reuse_ptr && (command & (expand_fwd | expand_bwd))){
if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){
void *ret = priv_expand_both_sides
(command, limit_size, preferred_size, received_size, reuse_ptr, true, backwards_multiple);
if(ret)
return return_type(ret, true);
}
if(command & allocate_new){
if(command & boost::interprocess::allocate_new){
size_block_ctrl_compare comp;
imultiset_iterator it(m_header.m_imultiset.lower_bound(preferred_units, comp));
@@ -965,7 +931,7 @@ std::pair<void *, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:
//Now try to expand both sides with min size
if(reuse_ptr && (command & (expand_fwd | expand_bwd))){
if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){
return return_type(priv_expand_both_sides
(command, limit_size, preferred_size, received_size, reuse_ptr, false, backwards_multiple), true);
}

View File

@@ -162,7 +162,11 @@ class offset_ptr
//!Dereferencing operator, if it is a null offset_ptr behavior
//! is undefined. Never throws.
reference operator* () const
{ return *(this->get()); }
{
pointer p = this->get();
reference r = *p;
return r;
}
//!Indexing operator.
//!Never throws.

View File

@@ -21,7 +21,7 @@
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/iterators.hpp>
#include <boost/interprocess/detail/transform_iterator.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/segment_manager_helper.hpp>
@@ -72,8 +72,7 @@ class segment_manager_base
/// @cond
//Experimental. Don't use
typedef typename MemoryAlgorithm::multiallocation_iterator multiallocation_iterator;
typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain;
typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain;
/// @endcond
@@ -123,38 +122,40 @@ class segment_manager_base
//Experimental. Dont' use.
//!Allocates n_elements of
//!elem_size bytes. Throws bad_alloc on failure.
multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements)
multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t num_elements)
{
multiallocation_iterator ret = MemoryAlgorithm::allocate_many(elem_bytes, num_elements);
if(!ret) throw bad_alloc();
return ret;
multiallocation_chain mem(MemoryAlgorithm::allocate_many(elem_bytes, num_elements));
if(mem.empty()) throw bad_alloc();
return boost::interprocess::move(mem);
}
//!Allocates n_elements, each one of
//!element_lenghts[i]*sizeof_element bytes. Throws bad_alloc on failure.
multiallocation_iterator allocate_many
multiallocation_chain allocate_many
(const std::size_t *element_lenghts, std::size_t n_elements, std::size_t sizeof_element = 1)
{
multiallocation_iterator ret = MemoryAlgorithm::allocate_many(element_lenghts, n_elements, sizeof_element);
if(!ret) throw bad_alloc();
return ret;
multiallocation_chain mem(MemoryAlgorithm::allocate_many(element_lenghts, n_elements, sizeof_element));
if(mem.empty()) throw bad_alloc();
return boost::interprocess::move(mem);
}
//!Allocates n_elements of
//!elem_size bytes. Returns a default constructed iterator on failure.
multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements, std::nothrow_t)
multiallocation_chain allocate_many
(std::size_t elem_bytes, std::size_t num_elements, std::nothrow_t)
{ return MemoryAlgorithm::allocate_many(elem_bytes, num_elements); }
//!Allocates n_elements, each one of
//!element_lenghts[i]*sizeof_element bytes.
//!Returns a default constructed iterator on failure.
multiallocation_iterator allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element, std::nothrow_t)
multiallocation_chain allocate_many
(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element, std::nothrow_t)
{ return MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element); }
//!Deallocates elements pointed by the
//!multiallocation iterator range.
void deallocate_many(multiallocation_iterator it)
{ MemoryAlgorithm::deallocate_many(it); }
void deallocate_many(multiallocation_chain chain)
{ MemoryAlgorithm::deallocate_many(boost::interprocess::move(chain)); }
/// @endcond
@@ -185,27 +186,27 @@ class segment_manager_base
template<class T>
std::pair<T *, bool>
allocation_command (allocation_type command, std::size_t limit_size,
allocation_command (boost::interprocess::allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
T *reuse_ptr = 0)
{
std::pair<T *, bool> ret = MemoryAlgorithm::allocation_command
( command | nothrow_allocation, limit_size, preferred_size, received_size
( command | boost::interprocess::nothrow_allocation, limit_size, preferred_size, received_size
, reuse_ptr);
if(!(command & nothrow_allocation) && !ret.first)
if(!(command & boost::interprocess::nothrow_allocation) && !ret.first)
throw bad_alloc();
return ret;
}
std::pair<void *, bool>
raw_allocation_command (allocation_type command, std::size_t limit_objects,
raw_allocation_command (boost::interprocess::allocation_type command, std::size_t limit_objects,
std::size_t preferred_objects,std::size_t &received_objects,
void *reuse_ptr = 0, std::size_t sizeof_object = 1)
{
std::pair<void *, bool> ret = MemoryAlgorithm::raw_allocation_command
( command | nothrow_allocation, limit_objects, preferred_objects, received_objects
( command | boost::interprocess::nothrow_allocation, limit_objects, preferred_objects, received_objects
, reuse_ptr, sizeof_object);
if(!(command & nothrow_allocation) && !ret.first)
if(!(command & boost::interprocess::nothrow_allocation) && !ret.first)
throw bad_alloc();
return ret;
}
@@ -297,7 +298,7 @@ class segment_manager_base
//scoped_lock<rmutex> guard(m_header);
//-------------------------------
if(ctrl_data->allocation_type() != anonymous_type){
if(ctrl_data->alloc_type() != anonymous_type){
//This is not an anonymous object, the pointer is wrong!
assert(0);
}
@@ -311,11 +312,6 @@ class segment_manager_base
/// @endcond
};
//These pointers are the ones the user will use to
//indicate previous allocation types
static const detail::anonymous_instance_t * anonymous_instance = 0;
static const detail::unique_instance_t * unique_instance = 0;
//!This object is placed in the beginning of memory segment and
//!implements the allocation (named or anonymous) of portions
//!of the segment. This object contains two indexes that
@@ -351,7 +347,6 @@ class segment_manager
typedef MemoryAlgorithm memory_algorithm;
typedef typename Base::void_pointer void_pointer;
typedef CharType char_type;
typedef typename Base::multiallocation_iterator multiallocation_iterator;
typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
@@ -672,6 +667,7 @@ class segment_manager
typename deleter<T>::type
get_deleter()
{ return typename deleter<T>::type(this); }
/// @cond
//!Generic named/anonymous new function. Offers all the possibilities,
@@ -753,7 +749,7 @@ class segment_manager
void priv_destroy_ptr(const void *ptr, detail::in_place_interface &dtor)
{
block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr, dtor.size, dtor.alignment);
switch(ctrl_data->allocation_type()){
switch(ctrl_data->alloc_type()){
case anonymous_type:
this->prot_anonymous_destroy(ptr, dtor);
break;
@@ -779,7 +775,7 @@ class segment_manager
//!functions. Does not throw
static const CharType *priv_get_instance_name(block_header_t *ctrl_data)
{
allocation_type type = ctrl_data->allocation_type();
boost::interprocess::allocation_type type = ctrl_data->alloc_type();
if(type != named_type){
assert((type == anonymous_type && ctrl_data->m_num_char == 0) ||
(type == unique_type && ctrl_data->m_num_char != 0) );
@@ -805,8 +801,8 @@ class segment_manager
static instance_type priv_get_instance_type(block_header_t *ctrl_data)
{
//Get header
assert((instance_type)ctrl_data->allocation_type() < max_allocation_type);
return (instance_type)ctrl_data->allocation_type();
assert((instance_type)ctrl_data->alloc_type() < max_allocation_type);
return (instance_type)ctrl_data->alloc_type();
}
static std::size_t priv_get_reserved_bytes()
@@ -1311,18 +1307,13 @@ class segment_manager
typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex;
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
scoped_lock<rmutex>
#else
detail::move_return<scoped_lock<rmutex> >
#endif
priv_get_lock(bool use_lock)
scoped_lock<rmutex> priv_get_lock(bool use_lock)
{
scoped_lock<rmutex> local(m_header, defer_lock);
if(use_lock){
local.lock();
}
return local;
return scoped_lock<rmutex>(boost::interprocess::move(local));
}
//!This struct includes needed data and derives from
@@ -1338,6 +1329,7 @@ class segment_manager
, m_unique_index(restricted_segment_mngr)
{}
} m_header;
/// @endcond
};

View File

@@ -22,10 +22,11 @@
#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
#include <cstddef>
#include <string>
#include <cstdio> //std::remove
#include <algorithm>
#ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
#if defined(BOOST_INTERPROCESS_SYSTEM_V_SHARED_MEMORY_OBJECTS)
# include <sys/shm.h> //System V shared memory...
#elif defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
# include <fcntl.h> //O_CREAT, O_*...
# include <sys/mman.h> //shm_xxx
# include <unistd.h> //ftruncate, close
@@ -46,11 +47,12 @@ class shared_memory_object
{
/// @cond
//Non-copyable and non-assignable
shared_memory_object(const shared_memory_object &);
shared_memory_object &operator=(const shared_memory_object &);
shared_memory_object(shared_memory_object &);
shared_memory_object &operator=(shared_memory_object &);
/// @endcond
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(shared_memory_object)
//!Default constructor. Represents an empty shared_memory_object.
shared_memory_object();
@@ -74,44 +76,22 @@ class shared_memory_object
//!Moves the ownership of "moved"'s shared memory object to *this.
//!After the call, "moved" does not represent any shared memory object.
//!Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
shared_memory_object(detail::moved_object<shared_memory_object> moved)
: m_handle(file_handle_t(detail::invalid_file()))
{ this->swap(moved.get()); }
#else
shared_memory_object(shared_memory_object &&moved)
shared_memory_object(BOOST_INTERPROCESS_RV_REF(shared_memory_object) moved)
: m_handle(file_handle_t(detail::invalid_file()))
{ this->swap(moved); }
#endif
//!Moves the ownership of "moved"'s shared memory to *this.
//!After the call, "moved" does not represent any shared memory.
//!Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
shared_memory_object &operator=
(detail::moved_object<shared_memory_object> moved)
shared_memory_object &operator=(BOOST_INTERPROCESS_RV_REF(shared_memory_object) moved)
{
shared_memory_object tmp(moved);
shared_memory_object tmp(boost::interprocess::move(moved));
this->swap(tmp);
return *this;
}
#else
shared_memory_object &operator=(shared_memory_object &&moved)
{
shared_memory_object tmp(detail::move_impl(moved));
this->swap(tmp);
return *this;
}
#endif
//!Swaps the shared_memory_objects. Does not throw
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
void swap(detail::moved_object<shared_memory_object> mother)
{ this->swap(mother.get()); }
void swap(shared_memory_object &other);
#else
void swap(shared_memory_object &&other);
#endif
void swap(shared_memory_object &moved);
//!Erases a shared memory object from the system.
//!Returns false on error. Never throws
@@ -173,11 +153,7 @@ inline const char *shared_memory_object::get_name() const
inline bool shared_memory_object::get_size(offset_t &size) const
{ return detail::get_file_size((file_handle_t)m_handle, size); }
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void shared_memory_object::swap(shared_memory_object &other)
#else
inline void shared_memory_object::swap(shared_memory_object &&other)
#endif
{
std::swap(m_handle, other.m_handle);
std::swap(m_mode, other.m_mode);
@@ -185,7 +161,9 @@ inline void shared_memory_object::swap(shared_memory_object &&other)
}
inline mapping_handle_t shared_memory_object::get_mapping_handle() const
{ return detail::mapping_handle_from_file_handle(m_handle); }
{
return detail::mapping_handle_from_file_handle(m_handle);
}
inline mode_t shared_memory_object::get_mode() const
{ return m_mode; }
@@ -229,7 +207,6 @@ inline bool shared_memory_object::priv_open_or_create
throw interprocess_exception(err);
}
//detail::delete_file_on_reboot_if_possible(shmfile.c_str());
m_mode = mode;
return true;
}
@@ -240,7 +217,7 @@ inline bool shared_memory_object::remove(const char *filename)
//Make sure a temporary path is created for shared memory
std::string shmfile;
detail::tmp_filename(filename, shmfile);
return std::remove(shmfile.c_str()) == 0;
return detail::delete_file(shmfile.c_str()) == 0;
}
catch(...){
return false;
@@ -355,14 +332,6 @@ inline void shared_memory_object::priv_close()
#endif
//!Trait class to detect if a type is
//!movable
template<>
struct is_movable<shared_memory_object>
{
enum { value = true };
};
///@endcond
//!A class that stores the name of a shared memory

View File

@@ -20,6 +20,7 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/pointer_to_other.hpp>
//!\file
//!Describes the functor to delete objects from the segment.
@@ -35,11 +36,11 @@ template<class T, class SegmentManager>
class deleter
{
public:
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename SegmentManager::void_pointer, T>::type pointer;
private:
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<pointer, SegmentManager>::type segment_manager_pointer;
segment_manager_pointer mp_mngr;

View File

@@ -24,6 +24,7 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/checked_delete.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp>
#include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp>
#include <boost/interprocess/detail/utilities.hpp>
@@ -41,20 +42,20 @@ template<class T, class VoidAllocator, class Deleter>
class shared_count
{
public:
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename VoidAllocator::pointer, T>::type pointer;
private:
typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename VoidAllocator::pointer, counted_impl>::type counted_impl_ptr;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename VoidAllocator::pointer, sp_counted_base>::type counted_base_ptr;
typedef typename VoidAllocator::template rebind
<counted_impl>::other counted_impl_allocator;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename VoidAllocator::pointer, const Deleter>::type const_deleter_pointer;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename VoidAllocator::pointer, const VoidAllocator>::type const_allocator_pointer;
pointer m_px;
@@ -212,14 +213,14 @@ template<class T, class VoidAllocator, class Deleter>
class weak_count
{
public:
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename VoidAllocator::pointer, T>::type pointer;
private:
typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename VoidAllocator::pointer, counted_impl>::type counted_impl_ptr;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename VoidAllocator::pointer, sp_counted_base>::type counted_base_ptr;
pointer m_px;

View File

@@ -26,6 +26,7 @@
#include <boost/interprocess/smart_ptr/detail/sp_counted_base.hpp>
#include <boost/interprocess/smart_ptr/scoped_ptr.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/pointer_to_other.hpp>
namespace boost {
@@ -33,6 +34,34 @@ namespace interprocess {
namespace detail {
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an object using a STL allocator.
template <class Allocator>
struct scoped_ptr_dealloc_functor
{
typedef typename Allocator::pointer pointer;
typedef detail::integral_constant<unsigned,
boost::interprocess::version<Allocator>::value> alloc_version;
typedef detail::integral_constant<unsigned, 1> allocator_v1;
typedef detail::integral_constant<unsigned, 2> allocator_v2;
private:
void priv_deallocate(const typename Allocator::pointer &p, allocator_v1)
{ m_alloc.deallocate(p, 1); }
void priv_deallocate(const typename Allocator::pointer &p, allocator_v2)
{ m_alloc.deallocate_one(p); }
public:
Allocator& m_alloc;
scoped_ptr_dealloc_functor(Allocator& a)
: m_alloc(a) {}
void operator()(pointer ptr)
{ if (ptr) priv_deallocate(ptr, alloc_version()); }
};
template<class A, class D>
class sp_counted_impl_pd
: public sp_counted_base
@@ -50,10 +79,10 @@ class sp_counted_impl_pd
sp_counted_impl_pd( sp_counted_impl_pd const & );
sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename A::pointer, const D>::type const_deleter_pointer;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename A::pointer, const A>::type const_allocator_pointer;
typedef typename D::pointer pointer;
@@ -73,7 +102,7 @@ class sp_counted_impl_pd
{ return const_allocator_pointer(&static_cast<const A&>(*this)); }
void dispose() // nothrow
{ static_cast<D&>(*this)(m_ptr); }
{ static_cast<D&>(*this)(m_ptr); }
void destroy() // nothrow
{
@@ -83,9 +112,8 @@ class sp_counted_impl_pd
BOOST_ASSERT(a_copy == *this);
this_pointer this_ptr (this);
//Do it now!
scoped_ptr<this_type,
scoped_ptr_dealloc_functor<this_allocator> >
deallocator(this_ptr, a_copy);
scoped_ptr< this_type, scoped_ptr_dealloc_functor<this_allocator> >
deleter(this_ptr, a_copy);
typedef typename this_allocator::value_type value_type;
detail::get_pointer(this_ptr)->~value_type();
}

View File

@@ -22,6 +22,7 @@
#include <boost/assert.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/pointer_to_other.hpp>
#include <functional> // for std::less
#include <iosfwd> // for std::basic_ostream
@@ -49,7 +50,7 @@ class intrusive_ptr
{
public:
//!Provides the type of the internal stored pointer.
typedef typename detail::pointer_to_other<VoidPointer, T>::type pointer;
typedef typename boost::pointer_to_other<VoidPointer, T>::type pointer;
//!Provides the type of the stored pointer.
typedef T element_type;

View File

@@ -19,6 +19,7 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/pointer_type.hpp>
#include <boost/assert.hpp>
#include <boost/pointer_to_other.hpp>
//!\file
//!Describes the smart pointer scoped_ptr
@@ -54,7 +55,7 @@ class scoped_ptr
typedef typename detail::pointer_type<T, Deleter>::type pointer;
//!Provides the type of the internal stored pointer
// typedef typename detail::pointer_to_other
// typedef typename boost::pointer_to_other
// <typename Deleter::pointer, T>::type pointer;
//!Constructs a scoped_ptr, storing a copy of p(which can be 0) and d.

View File

@@ -29,6 +29,7 @@
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/smart_ptr/deleter.hpp>
#include <boost/static_assert.hpp>
#include <boost/pointer_to_other.hpp>
#include <algorithm> // for std::swap
#include <functional> // for std::less
@@ -96,18 +97,20 @@ class shared_ptr
typedef T element_type;
typedef T value_type;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename VoidAllocator::pointer, T>::type pointer;
typedef typename detail::add_reference
<value_type>::type reference;
typedef typename detail::add_reference
<const value_type>::type const_reference;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename VoidAllocator::pointer, const Deleter>::type const_deleter_pointer;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename VoidAllocator::pointer, const VoidAllocator>::type const_allocator_pointer;
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(shared_ptr)
//!Constructs an empty shared_ptr.
//!Use_count() == 0 && get()== 0.
shared_ptr()
@@ -122,7 +125,7 @@ class shared_ptr
{
//Check that the pointer passed is of the same type that
//the pointer the allocator defines or it's a raw pointer
typedef typename detail::pointer_to_other<pointer, T>::type ParameterPointer;
typedef typename boost::pointer_to_other<pointer, T>::type ParameterPointer;
BOOST_STATIC_ASSERT((detail::is_same<pointer, ParameterPointer>::value) ||
(detail::is_pointer<pointer>::value));
detail::sp_enable_shared_from_this<T, VoidAllocator, Deleter>( m_pn, detail::get_pointer(p), detail::get_pointer(p) );
@@ -153,15 +156,9 @@ class shared_ptr
//!Move-Constructs a shared_ptr that takes ownership of other resource and
//!other is put in default-constructed state.
//!Throws: nothing.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
explicit shared_ptr(detail::moved_object<shared_ptr> other)
: m_pn()
{ this->swap(other.get()); }
#else
explicit shared_ptr(shared_ptr &&other)
explicit shared_ptr(BOOST_INTERPROCESS_RV_REF(shared_ptr) other)
: m_pn()
{ this->swap(other); }
#endif
/// @cond
template<class Y>
@@ -198,19 +195,11 @@ class shared_ptr
//!Move-assignment. Equivalent to shared_ptr(other).swap(*this).
//!Never throws
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
shared_ptr & operator=(detail::moved_object<shared_ptr> other) // never throws
shared_ptr & operator=(BOOST_INTERPROCESS_RV_REF(shared_ptr) other) // never throws
{
this_type(other).swap(*this);
return *this;
}
#else
shared_ptr & operator=(shared_ptr &&other) // never throws
{
this_type(other).swap(*this);
return *this;
}
#endif
//!This is equivalent to:
//!this_type().swap(*this);
@@ -226,7 +215,7 @@ class shared_ptr
{
//Check that the pointer passed is of the same type that
//the pointer the allocator defines or it's a raw pointer
typedef typename detail::pointer_to_other<Pointer, T>::type ParameterPointer;
typedef typename boost::pointer_to_other<Pointer, T>::type ParameterPointer;
BOOST_STATIC_ASSERT((detail::is_same<pointer, ParameterPointer>::value) ||
(detail::is_pointer<Pointer>::value));
this_type(p, a, d).swap(*this);
@@ -371,26 +360,6 @@ inline typename managed_shared_ptr<T, ManagedMemory>::type
);
}
/*
// get_deleter (experimental)
template<class T, class VoidAllocator, class Deleter>
typename detail::pointer_to_other<shared_ptr<T, VoidAllocator, Deleter>, Deleter>::type
get_deleter(shared_ptr<T, VoidAllocator, Deleter> const & p)
{ return static_cast<Deleter *>(p._internal_get_deleter(typeid(Deleter))); }
*/
/// @cond
//!This class has move constructor
template <class T, class VA, class D>
struct is_movable<boost::interprocess::shared_ptr<T, VA, D> >
{
enum { value = true };
};
/// @endcond
} // namespace interprocess
/// @cond

View File

@@ -88,6 +88,8 @@ class unique_ptr
/// @endcond
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(unique_ptr)
typedef T element_type;
typedef D deleter_type;
typedef typename detail::pointer_type<T, D>::type pointer;
@@ -142,7 +144,7 @@ class unique_ptr
//!
//!After the construction, u no longer owns a pointer.
//![ Note: The deleter constructor can be implemented with
//!std::detail::forward_impl<D>. -end note ]
//! boost::interprocess::forward<D>. -end note ]
//!
//!Postconditions: get() == value u.get() had before the construction.
//!get_deleter() returns a reference to the internally stored deleter which
@@ -150,15 +152,9 @@ class unique_ptr
//!deleter() and u.get_deleter() both reference the same lvalue deleter.
//!
//!Throws: nothing.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
unique_ptr(detail::moved_object<unique_ptr> u)
: ptr_(u.get().release(), detail::move_impl(u.get().get_deleter()))
unique_ptr(BOOST_INTERPROCESS_RV_REF(unique_ptr) u)
: ptr_(u.release(), boost::interprocess::forward<D>(u.get_deleter()))
{}
#else
unique_ptr(unique_ptr &&u)
: ptr_(u.release(), detail::forward_impl<D>(u.get_deleter()))
{}
#endif
//!Requires: If D is not a reference type, construction of the deleter
//!D from an rvalue of type E must be well formed
@@ -179,9 +175,8 @@ class unique_ptr
//!was constructed from u.get_deleter().
//!
//!Throws: nothing.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template <class U, class E>
unique_ptr(detail::moved_object<unique_ptr<U, E> > u,
unique_ptr(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u,
typename detail::enable_if_c<
detail::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
detail::is_convertible<E, D>::value &&
@@ -192,24 +187,8 @@ class unique_ptr
,
nat
>::type = nat())
: ptr_(const_cast<unique_ptr<U,E>&>(u.get()).release(), detail::move_impl(u.get().get_deleter()))
: ptr_(const_cast<unique_ptr<U,E>&>(u).release(), boost::interprocess::move<D>(u.get_deleter()))
{}
#else
template <class U, class E>
unique_ptr(unique_ptr<U, E> && u,
typename detail::enable_if_c<
detail::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
detail::is_convertible<E, D>::value &&
(
!detail::is_reference<D>::value ||
detail::is_same<D, E>::value
)
,
nat
>::type = nat())
: ptr_(const_cast<unique_ptr<U,E>&>(u).release(), detail::forward_impl<D>(u.get_deleter()))
{}
#endif
//!Effects: If get() == 0 there are no effects. Otherwise get_deleter()(get()).
//!
@@ -230,21 +209,12 @@ class unique_ptr
//!Returns: *this.
//!
//!Throws: nothing.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
unique_ptr& operator=(detail::moved_object<unique_ptr> u)
{
reset(u.get().release());
ptr_.second() = detail::move_impl(u.get().get_deleter());
return *this;
}
#else
unique_ptr& operator=(unique_ptr && u)
unique_ptr& operator=(BOOST_INTERPROCESS_RV_REF(unique_ptr) u)
{
reset(u.release());
ptr_.second() = detail::move_impl(u.get_deleter());
ptr_.second() = boost::interprocess::move(u.get_deleter());
return *this;
}
#endif
//!Requires: Assignment of the deleter D from an rvalue D must not
//!throw an exception. U* must be implicitly convertible to T*.
@@ -261,21 +231,12 @@ class unique_ptr
//!
//!Throws: nothing.
template <class U, class E>
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
unique_ptr& operator=(detail::moved_object<unique_ptr<U, E> > mu)
{
reset(mu.get().release());
ptr_.second() = detail::move_impl(mu.get().get_deleter());
return *this;
}
#else
unique_ptr& operator=(unique_ptr<U, E> && u)
unique_ptr& operator=(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u)
{
reset(u.release());
ptr_.second() = detail::move_impl(u.get_deleter());
ptr_.second() = boost::interprocess::move(u.get_deleter());
return *this;
}
#endif
//!Assigns from the literal 0 or NULL.
//!
@@ -359,23 +320,14 @@ class unique_ptr
//!Effects: The stored pointers of this and u are exchanged.
//! The stored deleters are swapped (unqualified).
//!Throws: nothing.
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
void swap(unique_ptr& u)
{ ptr_.swap(u.ptr_); }
void swap(detail::moved_object<unique_ptr> mu)
{ ptr_.swap(mu.get().ptr_); }
#else
void swap(unique_ptr&&u)
{ ptr_.swap(u.ptr_); }
#endif
/// @cond
private:
boost::compressed_pair<pointer, D> ptr_;
//This private constructor avoids moving from non-const lvalues
unique_ptr(const unique_ptr&);
unique_ptr(unique_ptr&);
template <class U, class E> unique_ptr(unique_ptr<U, E>&);
template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
@@ -570,16 +522,6 @@ 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(); }
/// @cond
//!This class has move constructor
template <class T, class D>
struct is_movable<unique_ptr<T, D> >
{
enum { value = true };
};
/// @endcond
//!Returns the type of a unique pointer
//!of type T with boost::interprocess::deleter deleter
@@ -597,20 +539,11 @@ struct managed_unique_ptr
//!with boost::interproces::deleter from a pointer
//!of type T that has been allocated in the passed managed segment
template<class T, class ManagedMemory>
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
inline typename detail::return_type
<typename managed_unique_ptr<T, ManagedMemory>::type
>::type
#else
typename managed_unique_ptr<T, ManagedMemory>::type
#endif
inline typename managed_unique_ptr<T, ManagedMemory>::type
make_managed_unique_ptr(T *constructed_object, ManagedMemory &managed_memory)
{
typename managed_unique_ptr<T, ManagedMemory>::type to_return
( constructed_object
, managed_memory.template get_deleter<T>()
);
return to_return;
return typename managed_unique_ptr<T, ManagedMemory>::type
(constructed_object, managed_memory.template get_deleter<T>());
}
} //namespace interprocess{

View File

@@ -22,6 +22,7 @@
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/smart_ptr/deleter.hpp>
#include <boost/pointer_to_other.hpp>
//!\file
//!Describes the smart pointer weak_ptr.
@@ -53,7 +54,7 @@ class weak_ptr
private:
// Borland 5.5.1 specific workarounds
typedef weak_ptr<T, A, D> this_type;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename A::pointer, T>::type pointer;
typedef typename detail::add_reference
<T>::type reference;

Some files were not shown because too many files have changed in this diff Show More