mirror of
https://github.com/boostorg/interprocess.git
synced 2026-01-19 04:12:13 +00:00
Changes for Boost.1.39
[SVN r52034]
This commit is contained in:
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
40
include/boost/interprocess/containers/allocation_type.hpp
Normal file
40
include/boost/interprocess/containers/allocation_type.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
1482
include/boost/interprocess/containers/container/deque.hpp
Normal file
1482
include/boost/interprocess/containers/container/deque.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
152
include/boost/interprocess/containers/container/detail/mpl.hpp
Normal file
152
include/boost/interprocess/containers/container/detail/mpl.hpp
Normal 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
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
189
include/boost/interprocess/containers/container/detail/pair.hpp
Normal file
189
include/boost/interprocess/containers/container/detail/pair.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
1390
include/boost/interprocess/containers/container/flat_map.hpp
Normal file
1390
include/boost/interprocess/containers/container/flat_map.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1172
include/boost/interprocess/containers/container/flat_set.hpp
Normal file
1172
include/boost/interprocess/containers/container/flat_set.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1372
include/boost/interprocess/containers/container/list.hpp
Normal file
1372
include/boost/interprocess/containers/container/list.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1266
include/boost/interprocess/containers/container/map.hpp
Normal file
1266
include/boost/interprocess/containers/container/map.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1112
include/boost/interprocess/containers/container/set.hpp
Normal file
1112
include/boost/interprocess/containers/container/set.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1524
include/boost/interprocess/containers/container/slist.hpp
Normal file
1524
include/boost/interprocess/containers/container/slist.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1352
include/boost/interprocess/containers/container/stable_vector.hpp
Normal file
1352
include/boost/interprocess/containers/container/stable_vector.hpp
Normal file
File diff suppressed because it is too large
Load Diff
2320
include/boost/interprocess/containers/container/string.hpp
Normal file
2320
include/boost/interprocess/containers/container/string.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1933
include/boost/interprocess/containers/container/vector.hpp
Normal file
1933
include/boost/interprocess/containers/container/vector.hpp
Normal file
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
32
include/boost/interprocess/containers/pair.hpp
Normal file
32
include/boost/interprocess/containers/pair.hpp
Normal 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
31
include/boost/interprocess/containers/stable_vector.hpp
Normal file
31
include/boost/interprocess/containers/stable_vector.hpp
Normal 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
33
include/boost/interprocess/containers/version_type.hpp
Normal file
33
include/boost/interprocess/containers/version_type.hpp
Normal 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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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&){
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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] != '/'){
|
||||
|
||||
180
include/boost/interprocess/detail/transform_iterator.hpp
Normal file
180
include/boost/interprocess/detail/transform_iterator.hpp
Normal 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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user