mirror of
https://github.com/boostorg/interprocess.git
synced 2026-01-19 04:12:13 +00:00
Adds uses-allocator-construction (for types where boost::container::uses_allocator<T>::value == true), in the following utilities:
- Segment managers in their `construct` methods - Allocators
This commit is contained in:
@@ -6785,6 +6785,10 @@ thank them:
|
||||
|
||||
[section:release_notes_boost_1_91_00 Boost 1.91 Release]
|
||||
|
||||
* Adds uses-allocator-construction (for types where `boost::container::uses_allocator<T>::value == true`), in the following utilities:
|
||||
* Segment managers in their `construct` methods
|
||||
* Allocators
|
||||
|
||||
* Fixed bugs:
|
||||
* [@https://github.com/boostorg/interprocess/issues/247 GitHub #247 (['"destruction of move-constructed map using private_adaptive_pool triggers Assertion"])].
|
||||
|
||||
|
||||
115
example/doc_complex_map_uses_allocator.cpp
Normal file
115
example/doc_complex_map_uses_allocator.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
//[doc_complex_map_uses_allocator
|
||||
#include <boost/interprocess/managed_shared_memory.hpp>
|
||||
#include <boost/interprocess/allocators/allocator.hpp>
|
||||
#include <boost/container/map.hpp>
|
||||
#include <boost/container/vector.hpp>
|
||||
#include <boost/container/string.hpp>
|
||||
//<-
|
||||
#include "../test/get_process_id_name.hpp"
|
||||
//->
|
||||
|
||||
using namespace boost::interprocess;
|
||||
|
||||
//Typedefs of allocators and containers
|
||||
typedef managed_shared_memory::segment_manager segment_manager_t;
|
||||
typedef allocator<void, segment_manager_t> void_allocator;
|
||||
typedef allocator<int, segment_manager_t> int_allocator;
|
||||
typedef boost::container::vector<int, int_allocator> int_vector;
|
||||
typedef allocator<int_vector, segment_manager_t> int_vector_allocator;
|
||||
typedef boost::container::vector<int_vector, int_vector_allocator> int_vector_vector;
|
||||
typedef allocator<char, segment_manager_t> char_allocator;
|
||||
typedef boost::container::basic_string<char, std::char_traits<char>, char_allocator> char_string;
|
||||
|
||||
class complex_data
|
||||
{
|
||||
int id_;
|
||||
char_string char_string_;
|
||||
int_vector_vector int_vector_vector_;
|
||||
|
||||
public:
|
||||
//Mark this class as uses-allocator construction-ready (see Boost.Container's docs)
|
||||
//Boost.Interprocess machinery will pass the allocator argument automatically if
|
||||
//constructors takes the allocator_type as the last argument of constructors
|
||||
typedef void_allocator allocator_type;
|
||||
|
||||
//Since void_allocator is convertible to any other allocator<T>, we can simplify
|
||||
//the initialization taking just one allocator for all inner containers.
|
||||
complex_data(int id, const char *name, const void_allocator &void_alloc)
|
||||
: id_(id), char_string_(name, void_alloc), int_vector_vector_(void_alloc)
|
||||
{}
|
||||
//Other members...
|
||||
//<-
|
||||
int get_id() { return id_; };
|
||||
char_string get_char_string() { return char_string_; };
|
||||
int_vector_vector get_int_vector_vector() { return int_vector_vector_; };
|
||||
//->
|
||||
};
|
||||
|
||||
//A transparent comparison functor
|
||||
//Allows creating associative container `value_type`s from comparable
|
||||
//types (e.g. shared memory string types from "const char *" arguments)
|
||||
struct less_transparent
|
||||
{
|
||||
typedef void is_transparent;
|
||||
|
||||
template<class T, class U>
|
||||
bool operator() (const T &t, const U &u) const
|
||||
{ return t < u; }
|
||||
};
|
||||
|
||||
//Definition of the map holding a string as key and complex_data as mapped type
|
||||
typedef std::pair<const char_string, complex_data> map_value_type;
|
||||
typedef std::pair<char_string, complex_data> movable_to_map_value_type;
|
||||
typedef allocator<map_value_type, segment_manager_t> map_value_type_allocator;
|
||||
typedef boost::container::map< char_string, complex_data
|
||||
, less_transparent, map_value_type_allocator> complex_map_type;
|
||||
|
||||
int main ()
|
||||
{
|
||||
//Remove shared memory on construction and destruction
|
||||
struct shm_remove
|
||||
{
|
||||
shm_remove() { shared_memory_object::remove(test::get_process_id_name()); }
|
||||
~shm_remove(){ shared_memory_object::remove(test::get_process_id_name()); }
|
||||
} remover;
|
||||
//<-
|
||||
(void)remover;
|
||||
//->
|
||||
|
||||
//Create shared memory
|
||||
managed_shared_memory segment(create_only, test::get_process_id_name(), 65536);
|
||||
|
||||
//Construct the shared memory map (associated with name "MyMap") and fill it using "extended uses allocator construction".
|
||||
//In this case "construct" tries to automatically pass the allocator argument to the constructed
|
||||
//type in addition to user-supplied arguments. "Uses-allocator construction" from the C++ standard
|
||||
//
|
||||
//In this case, no user arguments are provided, but the segment manager machinery has
|
||||
//detected that boost::container::map supports the user-allocator-construction protocol
|
||||
//so it automatically adds the allocator parameter and calls map::map(allocator_type) constructor.
|
||||
complex_map_type *mymap = segment.construct<complex_map_type>("MyMap")();
|
||||
|
||||
//This transparent insertion function plus uses-allocator construction so that
|
||||
//the programmer does not need to explicitly pass allocator instances. The container,
|
||||
//through boost::container::allocator::construct function, automatically adds the needed allocator
|
||||
//arguments without forcing the user to supply them, calling the following constructors:
|
||||
//
|
||||
//key_type --> basic_string(const char *, allocator_type)
|
||||
//mapped_type --> complex_data(int, const char *, allocator_type)
|
||||
//
|
||||
//The programmer only needs to specify the non-allocator arguments
|
||||
mymap->try_emplace("key_str", 3, "default_name");
|
||||
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -105,6 +105,7 @@ class adaptive_pool_base
|
||||
<const value_type>::type const_reference;
|
||||
typedef typename segment_manager::size_type size_type;
|
||||
typedef typename segment_manager::difference_type difference_type;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
typedef boost::interprocess::version_type<adaptive_pool_base, Version> version;
|
||||
typedef boost::container::dtl::transform_multiallocation_chain
|
||||
@@ -125,6 +126,8 @@ class adaptive_pool_base
|
||||
adaptive_pool_base& operator=
|
||||
(const adaptive_pool_base<Version2, T2, SegmentManager2, N2, F2, O2>&);
|
||||
|
||||
public:
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
@@ -174,8 +177,8 @@ class adaptive_pool_base
|
||||
{ return node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->get_segment_manager(); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager_t` and additional constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
@@ -189,7 +192,7 @@ class adaptive_pool_base
|
||||
{
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;
|
||||
boost::container::dtl::dispatch_uses_allocator
|
||||
(atd, this->get_segment_manager(), p, ::boost::forward<Args>(args)...);
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
@@ -200,7 +203,7 @@ class adaptive_pool_base
|
||||
{\
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;\
|
||||
boost::container::dtl::dispatch_uses_allocator\
|
||||
(atd, this->get_segment_manager(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ALLOCATORS_ADAPTIVE_POOL_CONSTRUCT_CODE)
|
||||
@@ -253,6 +256,8 @@ class adaptive_pool_v1
|
||||
typedef ipcdetail::adaptive_pool_base
|
||||
< 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
|
||||
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
@@ -263,6 +268,10 @@ class adaptive_pool_v1
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
adaptive_pool_v1(uses_segment_manager_t usm)
|
||||
: base_t(usm.get_segment_manager())
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
adaptive_pool_v1
|
||||
(const adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
@@ -311,7 +320,8 @@ class adaptive_pool
|
||||
typedef ipcdetail::adaptive_pool_base
|
||||
< 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
|
||||
public:
|
||||
typedef boost::interprocess::version_type<adaptive_pool, 2> version;
|
||||
typedef boost::interprocess::version_type<adaptive_pool, 2> version;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
@@ -323,6 +333,10 @@ class adaptive_pool
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
adaptive_pool(uses_segment_manager_t usm)
|
||||
: base_t(usm.get_segment_manager())
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
adaptive_pool
|
||||
(const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
@@ -419,8 +433,8 @@ class adaptive_pool
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const;
|
||||
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager_t` and additional constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
|
||||
@@ -105,6 +105,7 @@ class allocator
|
||||
<const value_type>::type const_reference;
|
||||
typedef typename segment_manager::size_type size_type;
|
||||
typedef typename segment_manager::difference_type difference_type;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
typedef boost::interprocess::version_type<allocator, 2> version;
|
||||
|
||||
@@ -113,6 +114,7 @@ class allocator
|
||||
//Experimental. Don't use.
|
||||
typedef boost::container::dtl::transform_multiallocation_chain
|
||||
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!Obtains an allocator that allocates
|
||||
@@ -133,6 +135,12 @@ class allocator
|
||||
allocator(segment_manager *segment_mngr)
|
||||
: mp_mngr(segment_mngr) { }
|
||||
|
||||
//!Constructor that enables uses-allocator
|
||||
//!Never throws
|
||||
allocator(uses_segment_manager_t usm)
|
||||
: mp_mngr(usm.get_segment_manager())
|
||||
{}
|
||||
|
||||
//!Constructor from other allocator.
|
||||
//!Never throws
|
||||
allocator(const allocator &other)
|
||||
@@ -161,8 +169,8 @@ class allocator
|
||||
{ mp_mngr->deallocate((void*)ipcdetail::to_raw_pointer(ptr)); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
@@ -176,7 +184,7 @@ class allocator
|
||||
{
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;
|
||||
boost::container::dtl::dispatch_uses_allocator
|
||||
(atd, this->get_segment_manager(), p, ::boost::forward<Args>(args)...);
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
@@ -187,7 +195,7 @@ class allocator
|
||||
{\
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;\
|
||||
boost::container::dtl::dispatch_uses_allocator\
|
||||
(atd, this->get_segment_manager(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ALLOCATORS_ALLOCATOR_CONSTRUCT_CODE)
|
||||
|
||||
@@ -72,6 +72,8 @@ class cached_adaptive_pool_v1
|
||||
>
|
||||
, 1> base_t;
|
||||
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
@@ -86,6 +88,11 @@ class cached_adaptive_pool_v1
|
||||
: base_t(segment_mngr, max_cached_nodes)
|
||||
{}
|
||||
|
||||
cached_adaptive_pool_v1(uses_segment_manager_t usm,
|
||||
size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
|
||||
: base_t(usm.get_segment_manager(), max_cached_nodes)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
cached_adaptive_pool_v1
|
||||
(const cached_adaptive_pool_v1
|
||||
@@ -160,6 +167,7 @@ class cached_adaptive_pool
|
||||
BOOST_COPYABLE_AND_MOVABLE_ALT(cached_adaptive_pool)
|
||||
public:
|
||||
typedef boost::interprocess::version_type<cached_adaptive_pool, 2> version;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
@@ -173,6 +181,11 @@ class cached_adaptive_pool
|
||||
: base_t(segment_mngr, max_cached_nodes)
|
||||
{}
|
||||
|
||||
cached_adaptive_pool(uses_segment_manager_t usm,
|
||||
std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
|
||||
: base_t(usm.get_segment_manager(), max_cached_nodes)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
cached_adaptive_pool
|
||||
(const cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
@@ -281,8 +294,8 @@ class cached_adaptive_pool
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const;
|
||||
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager_t` and additional constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
|
||||
@@ -69,6 +69,7 @@ class cached_node_allocator_v1
|
||||
, NodesPerBlock
|
||||
>
|
||||
, 1> base_t;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
@@ -84,6 +85,11 @@ class cached_node_allocator_v1
|
||||
: base_t(segment_mngr, max_cached_nodes)
|
||||
{}
|
||||
|
||||
cached_node_allocator_v1(uses_segment_manager_t usm,
|
||||
size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
|
||||
: base_t(usm.get_segment_manager(), max_cached_nodes)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
cached_node_allocator_v1
|
||||
(const cached_node_allocator_v1
|
||||
@@ -135,8 +141,9 @@ class cached_node_allocator
|
||||
BOOST_COPYABLE_AND_MOVABLE_ALT(cached_node_allocator)
|
||||
|
||||
public:
|
||||
typedef boost::interprocess::version_type<cached_node_allocator, 2> version;
|
||||
typedef typename base_t::size_type size_type;
|
||||
typedef boost::interprocess::version_type<cached_node_allocator, 2> version;
|
||||
typedef typename base_t::size_type size_type;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
@@ -149,6 +156,11 @@ class cached_node_allocator
|
||||
: base_t(segment_mngr, max_cached_nodes)
|
||||
{}
|
||||
|
||||
cached_node_allocator(uses_segment_manager_t usm,
|
||||
size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
|
||||
: base_t(usm.get_segment_manager(), max_cached_nodes)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
cached_node_allocator
|
||||
(const cached_node_allocator<T2, SegmentManager, NodesPerBlock> &other)
|
||||
@@ -253,8 +265,8 @@ class cached_node_allocator
|
||||
//!Never throws
|
||||
pointer address(reference value) const;
|
||||
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager_t` and additional constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
|
||||
@@ -78,6 +78,21 @@ struct sizeof_value<const volatile void>
|
||||
static const std::size_t value = sizeof(void*);
|
||||
};
|
||||
|
||||
template<class SegmentManager>
|
||||
class uses_segment_manager
|
||||
{
|
||||
private:
|
||||
SegmentManager *const m_mngr;
|
||||
|
||||
public:
|
||||
explicit uses_segment_manager(SegmentManager *mngr)
|
||||
: m_mngr(mngr)
|
||||
{}
|
||||
|
||||
SegmentManager *get_segment_manager()
|
||||
{ return m_mngr; }
|
||||
};
|
||||
|
||||
namespace ipcdetail {
|
||||
|
||||
//!Object function that creates the node allocator if it is not created and
|
||||
@@ -582,6 +597,7 @@ class cached_allocator_impl
|
||||
typedef typename base_t::size_type size_type;
|
||||
typedef typename base_t::multiallocation_chain multiallocation_chain;
|
||||
typedef typename base_t::value_type value_type;
|
||||
typedef uses_segment_manager<segment_manager> uses_segment_manager_t;
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE_ALT(cached_allocator_impl)
|
||||
|
||||
@@ -621,8 +637,8 @@ class cached_allocator_impl
|
||||
{ return m_cache.get_segment_manager(); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager_t` and additional constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
@@ -636,7 +652,7 @@ class cached_allocator_impl
|
||||
{
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;
|
||||
boost::container::dtl::dispatch_uses_allocator
|
||||
(atd, this->get_segment_manager(), p, ::boost::forward<Args>(args)...);
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
@@ -647,7 +663,7 @@ class cached_allocator_impl
|
||||
{\
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;\
|
||||
boost::container::dtl::dispatch_uses_allocator\
|
||||
(atd, this->get_segment_manager(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ALLOCATORS_ALLOCATOR_COMMON_CONSTRUCT_CODE)
|
||||
|
||||
@@ -106,6 +106,7 @@ class node_allocator_base
|
||||
typedef boost::interprocess::version_type<node_allocator_base, Version> version;
|
||||
typedef boost::container::dtl::transform_multiallocation_chain
|
||||
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
//!Obtains node_allocator_base from
|
||||
//!node_allocator_base
|
||||
@@ -173,8 +174,8 @@ class node_allocator_base
|
||||
{ return node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->get_segment_manager(); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager_t` and additional constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
@@ -188,7 +189,7 @@ class node_allocator_base
|
||||
{
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;
|
||||
boost::container::dtl::dispatch_uses_allocator
|
||||
(atd, this->get_segment_manager(), p, ::boost::forward<Args>(args)...);
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
@@ -199,7 +200,7 @@ class node_allocator_base
|
||||
{\
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;\
|
||||
boost::container::dtl::dispatch_uses_allocator\
|
||||
(atd, this->get_segment_manager(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ALLOCATORS_NODE_ALLOCATOR_CONSTRUCT_CODE)
|
||||
@@ -258,6 +259,10 @@ class node_allocator_v1
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
node_allocator_v1(typename base_t::uses_segment_manager_t usm)
|
||||
: base_t(usm.get_segment_manager())
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
node_allocator_v1
|
||||
(const node_allocator_v1<T2, SegmentManager, NodesPerBlock> &other)
|
||||
@@ -308,6 +313,10 @@ class node_allocator
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
node_allocator(typename base_t::uses_segment_manager_t usm)
|
||||
: base_t(usm.get_segment_manager())
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
node_allocator
|
||||
(const node_allocator<T2, SegmentManager, NodesPerBlock> &other)
|
||||
@@ -404,8 +413,8 @@ class node_allocator
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const;
|
||||
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager_t` and additional constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
|
||||
@@ -104,6 +104,7 @@ class private_adaptive_pool_base
|
||||
<private_adaptive_pool_base, Version> version;
|
||||
typedef boost::container::dtl::transform_multiallocation_chain
|
||||
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
//!Obtains node_allocator from other node_allocator
|
||||
template<class T2>
|
||||
@@ -178,8 +179,8 @@ class private_adaptive_pool_base
|
||||
{ return m_node_pool.get_segment_manager(); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager_t` and additional constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
@@ -193,7 +194,7 @@ class private_adaptive_pool_base
|
||||
{
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;
|
||||
boost::container::dtl::dispatch_uses_allocator
|
||||
(atd, this->get_segment_manager(), p, ::boost::forward<Args>(args)...);
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
@@ -204,7 +205,7 @@ class private_adaptive_pool_base
|
||||
{\
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;\
|
||||
boost::container::dtl::dispatch_uses_allocator\
|
||||
(atd, this->get_segment_manager(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ALLOCATORS_PRIVATE_ADAPTIVE_POOL_CONSTRUCT_CODE)
|
||||
@@ -260,6 +261,7 @@ class private_adaptive_pool_v1
|
||||
typedef ipcdetail::private_adaptive_pool_base
|
||||
< 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
|
||||
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
@@ -270,6 +272,10 @@ class private_adaptive_pool_v1
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
private_adaptive_pool_v1(uses_segment_manager_t usm)
|
||||
: base_t(usm.get_segment_manager())
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
private_adaptive_pool_v1
|
||||
(const private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
@@ -327,7 +333,8 @@ class private_adaptive_pool
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE_ALT(private_adaptive_pool)
|
||||
public:
|
||||
typedef boost::interprocess::version_type<private_adaptive_pool, 2> version;
|
||||
typedef boost::interprocess::version_type<private_adaptive_pool, 2> version;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
@@ -340,6 +347,10 @@ class private_adaptive_pool
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
private_adaptive_pool(uses_segment_manager_t usm)
|
||||
: base_t(usm.get_segment_manager())
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
private_adaptive_pool
|
||||
(const private_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
@@ -449,8 +460,8 @@ class private_adaptive_pool
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const;
|
||||
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager_t` and additional constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
|
||||
@@ -66,6 +66,7 @@ class private_node_allocator_base
|
||||
//Segment manager
|
||||
typedef SegmentManager segment_manager;
|
||||
typedef typename SegmentManager::void_pointer void_pointer;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
@@ -168,8 +169,8 @@ class private_node_allocator_base
|
||||
{ return m_node_pool.get_segment_manager(); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager_t` and additional constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
@@ -183,7 +184,7 @@ class private_node_allocator_base
|
||||
{
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;
|
||||
boost::container::dtl::dispatch_uses_allocator
|
||||
(atd, this->get_segment_manager(), p, ::boost::forward<Args>(args)...);
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
@@ -194,7 +195,7 @@ class private_node_allocator_base
|
||||
{\
|
||||
boost::container::dtl::allocator_traits_dummy<U> atd;\
|
||||
boost::container::dtl::dispatch_uses_allocator\
|
||||
(atd, this->get_segment_manager(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
(atd, uses_segment_manager_t(this->get_segment_manager()), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ALLOCATORS_PRIVATE_NODE_ALLOCATOR_CONSTRUCT_CODE)
|
||||
@@ -245,6 +246,7 @@ class private_node_allocator_v1
|
||||
public:
|
||||
typedef ipcdetail::private_node_allocator_base
|
||||
< 1, T, SegmentManager, NodesPerBlock> base_t;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
@@ -256,6 +258,10 @@ class private_node_allocator_v1
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
private_node_allocator_v1(uses_segment_manager_t usm)
|
||||
: base_t(usm.get_segment_manager())
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
private_node_allocator_v1
|
||||
(const private_node_allocator_v1<T2, SegmentManager, NodesPerBlock> &other)
|
||||
@@ -302,7 +308,9 @@ class private_node_allocator
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE_ALT(private_node_allocator)
|
||||
public:
|
||||
typedef boost::interprocess::version_type<private_node_allocator, 2> version;
|
||||
typedef boost::interprocess::version_type<private_node_allocator, 2> version;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
@@ -315,6 +323,10 @@ class private_node_allocator
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
private_node_allocator(uses_segment_manager_t usm)
|
||||
: base_t(usm.get_segment_manager())
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
private_node_allocator
|
||||
(const private_node_allocator<T2, SegmentManager, NodesPerBlock> &other)
|
||||
@@ -424,8 +436,8 @@ class private_node_allocator
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const;
|
||||
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `segment_manager*` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator argument
|
||||
//! `uses_segment_manager_t` and additional constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include <boost/interprocess/detail/variadic_templates_tools.hpp>
|
||||
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
#include <boost/container/detail/placement_new.hpp>
|
||||
#include <boost/container/detail/dispatch_uses_allocator.hpp>
|
||||
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
@@ -73,13 +75,14 @@ struct CtorArgN
|
||||
: args_(args...)
|
||||
{}
|
||||
|
||||
void construct_n(void *mem, std::size_t num)
|
||||
template<class SegmentManager>
|
||||
void construct_n(void *mem, SegmentManager *segment_manager, std::size_t num)
|
||||
{
|
||||
std::size_t constructed = 0;
|
||||
BOOST_INTERPROCESS_TRY{
|
||||
T* memory = static_cast<T*>(mem);
|
||||
for(constructed = 0; constructed < num; ++constructed){
|
||||
this->construct(memory++, IsIterator(), index_tuple_t());
|
||||
this->construct(memory++, segment_manager, IsIterator(), index_tuple_t());
|
||||
this->do_increment(IsIterator(), index_tuple_t());
|
||||
}
|
||||
}
|
||||
@@ -90,14 +93,26 @@ struct CtorArgN
|
||||
}
|
||||
|
||||
private:
|
||||
template<std::size_t ...IdxPack>
|
||||
void construct(void *mem, true_, const index_tuple<IdxPack...>&)
|
||||
{ ::new((void*)mem, boost_container_new_t()) T(*boost::forward<Args>((get<IdxPack>)(args_))...); }
|
||||
template<class SegmentManager, std::size_t ...IdxPack>
|
||||
void construct(void* mem, SegmentManager *segment_manager, true_, const index_tuple<IdxPack...>&)
|
||||
{
|
||||
boost::container::dtl::allocator_traits_dummy<T> atd;
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
boost::container::dtl::dispatch_uses_allocator
|
||||
(atd, uses_segment_manager_t(segment_manager), static_cast<T*>(mem), *boost::forward<Args>((get<IdxPack>)(args_))...);
|
||||
}
|
||||
|
||||
template<std::size_t ...IdxPack>
|
||||
void construct(void *mem, false_, const index_tuple<IdxPack...>&)
|
||||
{ ::new((void*)mem, boost_container_new_t()) T(boost::forward<Args>((get<IdxPack>)(args_))...); }
|
||||
//{ ::new((void*)mem, boost_container_new_t()) T(*boost::forward<Args>((get<IdxPack>)(args_))...); }
|
||||
|
||||
template<class SegmentManager, std::size_t ...IdxPack>
|
||||
void construct(void *mem, SegmentManager *segment_manager, false_, const index_tuple<IdxPack...>&)
|
||||
{
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
|
||||
boost::container::dtl::allocator_traits_dummy<T> atd;
|
||||
boost::container::dtl::dispatch_uses_allocator
|
||||
(atd, uses_segment_manager_t(segment_manager), static_cast<T*>(mem), boost::forward<Args>((get<IdxPack>)(args_))...);
|
||||
}
|
||||
|
||||
template<std::size_t ...IdxPack>
|
||||
void do_increment(true_, const index_tuple<IdxPack...>&)
|
||||
{
|
||||
@@ -163,13 +178,17 @@ struct CtorArg##N\
|
||||
CtorArg##N ( BOOST_MOVE_UREF##N )\
|
||||
BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\
|
||||
\
|
||||
void construct_n(void *mem, std::size_t num)\
|
||||
template<class SegmentManager>\
|
||||
void construct_n(void *mem, SegmentManager *segment_manager, std::size_t num)\
|
||||
{\
|
||||
std::size_t constructed = 0;\
|
||||
BOOST_INTERPROCESS_TRY{\
|
||||
T* memory = static_cast<T*>(mem);\
|
||||
for (constructed = 0; constructed < num; ++constructed) {\
|
||||
::new((void*)memory++) T ( BOOST_MOVE_MFWD##N );\
|
||||
boost::container::dtl::allocator_traits_dummy<T> atd;\
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;\
|
||||
boost::container::dtl::dispatch_uses_allocator\
|
||||
(atd, uses_segment_manager_t(segment_manager), memory++ BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
|
||||
}\
|
||||
}\
|
||||
BOOST_INTERPROCESS_CATCH(...) {\
|
||||
@@ -201,13 +220,17 @@ struct CtorIt##N\
|
||||
CtorIt##N ( BOOST_MOVE_VAL##N )\
|
||||
BOOST_MOVE_COLON##N BOOST_MOVE_VAL_INIT##N{}\
|
||||
\
|
||||
void construct_n(void *mem, std::size_t num)\
|
||||
template<class SegmentManager>\
|
||||
void construct_n(void *mem, SegmentManager *segment_manager, std::size_t num)\
|
||||
{\
|
||||
std::size_t constructed = 0;\
|
||||
BOOST_INTERPROCESS_TRY{\
|
||||
T* memory = static_cast<T*>(mem);\
|
||||
for(constructed = 0; constructed < num; ++constructed){\
|
||||
::new((void*)memory++) T( BOOST_MOVE_MITFWD##N );\
|
||||
boost::container::dtl::allocator_traits_dummy<T> atd;\
|
||||
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;\
|
||||
boost::container::dtl::dispatch_uses_allocator\
|
||||
(atd, uses_segment_manager_t(segment_manager), memory++ BOOST_MOVE_I##N BOOST_MOVE_MITFWD##N);\
|
||||
++(*this);\
|
||||
}\
|
||||
}\
|
||||
|
||||
@@ -734,7 +734,7 @@ class segment_manager
|
||||
ptr = hdr->value();
|
||||
|
||||
//Now call constructors
|
||||
pr.construct_n(ptr, num);
|
||||
pr.construct_n(ptr, this, num);
|
||||
|
||||
//All constructors successful, disable rollback
|
||||
mem.release();
|
||||
@@ -1109,7 +1109,7 @@ class segment_manager
|
||||
value_eraser<index_t> v_eraser(index, it);
|
||||
|
||||
//Construct array, this can throw
|
||||
pr.construct_n(ptr, num);
|
||||
pr.construct_n(ptr, this, num);
|
||||
|
||||
//Release rollbacks since construction was successful
|
||||
v_eraser.release();
|
||||
|
||||
Reference in New Issue
Block a user