namespace container {
namespace dtl {
-BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_compare)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(key_compare)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(key_equal)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(hasher)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(predicate_type)
template<class Allocator, class ICont>
struct node_alloc_holder
+ : public allocator_traits<Allocator>::template
+ portable_rebind_alloc<typename ICont::value_type>::type //NodeAlloc
{
//If the intrusive container is an associative container, obtain the predicate, which will
- //be of type node_compare<>. If not an associative container value_compare will be a "nat" type.
+ //be of type node_compare<>. If not an associative container val_compare will be a "nat" type.
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
( boost::container::dtl::
- , ICont, value_compare, dtl::nat) intrusive_value_compare;
+ , ICont, key_compare, dtl::nat) intrusive_val_compare;
//In that case obtain the value predicate from the node predicate via predicate_type
- //if intrusive_value_compare is node_compare<>, nat otherwise
+ //if intrusive_val_compare is node_compare<>, nat otherwise
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
( boost::container::dtl::
- , intrusive_value_compare
- , predicate_type, dtl::nat) value_compare;
+ , intrusive_val_compare
+ , predicate_type, dtl::nat) val_compare;
+
+ //If the intrusive container is a hash container, obtain the predicate, which will
+ //be of type node_compare<>. If not an associative container val_equal will be a "nat" type.
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+ (boost::container::dtl::
+ , ICont, key_equal, dtl::nat2) intrusive_val_equal;
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+ (boost::container::dtl::
+ , ICont, hasher, dtl::nat3) intrusive_val_hasher;
+ //In that case obtain the value predicate from the node predicate via predicate_type
+ //if intrusive_val_compare is node_compare<>, nat otherwise
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+ (boost::container::dtl::
+ , intrusive_val_equal
+ , predicate_type, dtl::nat2) val_equal;
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+ (boost::container::dtl::
+ , intrusive_val_hasher
+ , predicate_type, dtl::nat3) val_hasher;
typedef allocator_traits<Allocator> allocator_traits_type;
- typedef typename allocator_traits_type::value_type value_type;
+ typedef typename allocator_traits_type::value_type val_type;
typedef ICont intrusive_container;
typedef typename ICont::value_type Node;
typedef typename allocator_traits_type::template
//Constructors for sequence containers
node_alloc_holder()
- : members_()
{}
explicit node_alloc_holder(const ValAlloc &a)
- : members_(a)
+ : NodeAlloc(a)
{}
//Constructors for associative containers
- node_alloc_holder(const value_compare &c, const ValAlloc &a)
- : members_(a, c)
+ node_alloc_holder(const val_compare &c, const ValAlloc &a)
+ : NodeAlloc(a), m_icont(typename ICont::key_compare(c))
+ {}
+
+ node_alloc_holder(const val_hasher &hf, const val_equal &eql, const ValAlloc &a)
+ : NodeAlloc(a)
+ , m_icont(typename ICont::bucket_traits()
+ , typename ICont::hasher(hf)
+ , typename ICont::key_equal(eql))
+ {}
+
+ node_alloc_holder(const val_hasher &hf, const ValAlloc &a)
+ : NodeAlloc(a)
+ , m_icont(typename ICont::bucket_traits()
+ , typename ICont::hasher(hf)
+ , typename ICont::key_equal())
+ {}
+
+ node_alloc_holder(const val_hasher &hf)
+ : m_icont(typename ICont::bucket_traits()
+ , typename ICont::hasher(hf)
+ , typename ICont::key_equal())
{}
explicit node_alloc_holder(const node_alloc_holder &x)
- : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
+ : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
{}
- node_alloc_holder(const node_alloc_holder &x, const value_compare &c)
- : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c)
+ node_alloc_holder(const node_alloc_holder &x, const val_compare &c)
+ : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
+ , m_icont(typename ICont::key_compare(c))
+ {}
+
+ node_alloc_holder(const node_alloc_holder &x, const val_hasher &hf, const val_equal &eql)
+ : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
+ , m_icont( typename ICont::bucket_traits()
+ , typename ICont::hasher(hf)
+ , typename ICont::key_equal(eql))
+ {}
+
+ node_alloc_holder(const val_hasher &hf, const val_equal &eql)
+ : m_icont(typename ICont::bucket_traits()
+ , typename ICont::hasher(hf)
+ , typename ICont::key_equal(eql))
{}
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x)
- : members_(boost::move(x.node_alloc()))
+ : NodeAlloc(boost::move(x.node_alloc()))
{ this->icont().swap(x.icont()); }
- explicit node_alloc_holder(const value_compare &c)
- : members_(c)
+ explicit node_alloc_holder(const val_compare &c)
+ : m_icont(typename ICont::key_compare(c))
{}
//helpers for move assignments
- explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const value_compare &c)
- : members_(boost::move(x.node_alloc()), c)
+ explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const val_compare &c)
+ : NodeAlloc(boost::move(x.node_alloc())), m_icont(typename ICont::key_compare(c))
{ this->icont().swap(x.icont()); }
+ explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const val_hasher &hf, const val_equal &eql)
+ : NodeAlloc(boost::move(x.node_alloc()))
+ , m_icont( typename ICont::bucket_traits()
+ , typename ICont::hasher(hf)
+ , typename ICont::key_equal(eql))
+ { this->icont().swap(x.icont()); }
+
void copy_assign_alloc(const node_alloc_holder &x)
{
dtl::bool_<allocator_traits_type::propagate_on_container_copy_assignment::value> flag;
- dtl::assign_alloc( static_cast<NodeAlloc &>(this->members_)
- , static_cast<const NodeAlloc &>(x.members_), flag);
+ dtl::assign_alloc( static_cast<NodeAlloc &>(*this)
+ , static_cast<const NodeAlloc &>(x), flag);
}
void move_assign_alloc( node_alloc_holder &x)
{
dtl::bool_<allocator_traits_type::propagate_on_container_move_assignment::value> flag;
- dtl::move_alloc( static_cast<NodeAlloc &>(this->members_)
- , static_cast<NodeAlloc &>(x.members_), flag);
+ dtl::move_alloc( static_cast<NodeAlloc &>(*this)
+ , static_cast<NodeAlloc &>(x), flag);
}
~node_alloc_holder()
NodePtr create_node(Args &&...args)
{
NodePtr p = this->allocate_one();
- Deallocator node_deallocator(p, this->node_alloc());
- allocator_traits<NodeAlloc>::construct
- ( this->node_alloc()
- , dtl::addressof(p->m_data), boost::forward<Args>(args)...);
- node_deallocator.release();
- //This does not throw
- typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
+ BOOST_TRY{
+ ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;
+ allocator_traits<NodeAlloc>::construct
+ (this->node_alloc()
+ , p->get_real_data_ptr(), boost::forward<Args>(args)...);
+ }
+ BOOST_CATCH(...) {
+ p->destroy_header();
+ this->node_alloc().deallocate(p, 1);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
return (p);
}
NodePtr create_node(BOOST_MOVE_UREF##N)\
{\
NodePtr p = this->allocate_one();\
- Deallocator node_deallocator(p, this->node_alloc());\
- allocator_traits<NodeAlloc>::construct\
- ( this->node_alloc()\
- , dtl::addressof(p->m_data)\
- BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
- node_deallocator.release();\
- typedef typename Node::hook_type hook_type;\
- ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;\
+ BOOST_TRY{\
+ ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;\
+ allocator_traits<NodeAlloc>::construct\
+ ( this->node_alloc()\
+ , p->get_real_data_ptr()\
+ BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ }\
+ BOOST_CATCH(...) {\
+ p->destroy_header();\
+ this->node_alloc().deallocate(p, 1);\
+ BOOST_RETHROW\
+ }\
+ BOOST_CATCH_END\
return (p);\
}\
//
NodePtr create_node_from_it(const It &it)
{
NodePtr p = this->allocate_one();
- Deallocator node_deallocator(p, this->node_alloc());
- ::boost::container::construct_in_place(this->node_alloc(), dtl::addressof(p->m_data), it);
- node_deallocator.release();
- //This does not throw
- typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
+ BOOST_TRY{
+ ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;
+ ::boost::container::construct_in_place(this->node_alloc(), p->get_real_data_ptr(), it);
+ }
+ BOOST_CATCH(...) {
+ p->destroy_header();
+ this->node_alloc().deallocate(p, 1);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
return (p);
}
NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key)
{
NodePtr p = this->allocate_one();
- NodeAlloc &na = this->node_alloc();
- Deallocator node_deallocator(p, this->node_alloc());
- node_allocator_traits_type::construct
- (na, dtl::addressof(p->m_data.first), boost::forward<KeyConvertible>(key));
BOOST_TRY{
- node_allocator_traits_type::construct(na, dtl::addressof(p->m_data.second));
+ ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;
+ NodeAlloc &na = this->node_alloc();
+ node_allocator_traits_type::construct
+ (na, dtl::addressof(p->get_real_data().first), boost::forward<KeyConvertible>(key));
+ BOOST_TRY{
+ node_allocator_traits_type::construct(na, dtl::addressof(p->get_real_data().second));
+ }
+ BOOST_CATCH(...){
+ node_allocator_traits_type::destroy(na, dtl::addressof(p->get_real_data().first));
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
}
- BOOST_CATCH(...){
- node_allocator_traits_type::destroy(na, dtl::addressof(p->m_data.first));
- BOOST_RETHROW;
+ BOOST_CATCH(...) {
+ p->destroy_header();
+ this->node_alloc().deallocate(p, 1);
+ BOOST_RETHROW
}
BOOST_CATCH_END
- node_deallocator.release();
- //This does not throw
- typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
return (p);
}
(FwdIterator beg, difference_type n, Inserter inserter)
{
if(n){
- typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain;
+ typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain_t;
//Try to allocate memory in a single block
- typedef typename multiallocation_chain::iterator multialloc_iterator;
- multiallocation_chain mem;
+ typedef typename multiallocation_chain_t::iterator multialloc_iterator_t;
+ multiallocation_chain_t chain;
NodeAlloc &nalloc = this->node_alloc();
- node_allocator_version_traits_type::allocate_individual(nalloc, n, mem);
- multialloc_iterator itbeg(mem.begin()), itlast(mem.last());
- mem.clear();
+ node_allocator_version_traits_type::allocate_individual(nalloc, n, chain);
+ multialloc_iterator_t itbeg = chain.begin();
+ multialloc_iterator_t itlast = chain.last();
+ chain.clear();
+
Node *p = 0;
- BOOST_TRY{
+ BOOST_TRY{
Deallocator node_deallocator(NodePtr(), nalloc);
dtl::scoped_destructor<NodeAlloc> sdestructor(nalloc, 0);
- while(n--){
+ while(n){
+ --n;
p = boost::movelib::iterator_to_raw_pointer(itbeg);
+ ++itbeg; //Increment iterator before overwriting pointed memory
+ //This does not throw
+ p = ::new(p, boost_container_new_t()) Node;
node_deallocator.set(p);
- ++itbeg;
//This can throw
- boost::container::construct_in_place(nalloc, dtl::addressof(p->m_data), beg);
+ boost::container::construct_in_place(nalloc, p->get_real_data_ptr(), beg);
sdestructor.set(p);
++beg;
- //This does not throw
- typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(p), boost_container_new_t()) hook_type;
//This can throw in some containers (predicate might throw).
//(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception)
inserter(*p);
node_deallocator.release();
}
BOOST_CATCH(...){
- mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n);
- node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), mem);
+ p->destroy_header();
+ chain.incorporate_after(chain.last(), &*itbeg, &*itlast, n);
+ node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), chain);
BOOST_RETHROW
}
BOOST_CATCH_END
{}
NodePtr operator()(const Node &other) const
- { return m_holder.create_node(other.m_data); }
+ { return m_holder.create_node(other.get_real_data()); }
node_alloc_holder &m_holder;
};
{}
NodePtr operator()(Node &other)
- { //Use m_data instead of get_data to allow moving const key in [multi]map
- return m_holder.create_node(::boost::move(other.m_data));
+ { //Use get_real_data() instead of get_real_data to allow moving const key in [multi]map
+ return m_holder.create_node(::boost::move(other.get_real_data()));
}
node_alloc_holder &m_holder;
};
- struct members_holder
- : public NodeAlloc
- {
- private:
- members_holder(const members_holder&);
- members_holder & operator=(const members_holder&);
-
- public:
- members_holder()
- : NodeAlloc(), m_icont()
- {}
-
- template<class ConvertibleToAlloc>
- explicit members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc)
- : NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
- , m_icont()
- {}
-
- template<class ConvertibleToAlloc>
- members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const value_compare &c)
- : NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
- , m_icont(typename ICont::key_compare(c))
- {}
-
- explicit members_holder(const value_compare &c)
- : NodeAlloc()
- , m_icont(typename ICont::key_compare(c))
- {}
-
- //The intrusive container
- ICont m_icont;
- };
-
ICont &non_const_icont() const
- { return const_cast<ICont&>(this->members_.m_icont); }
+ { return const_cast<ICont&>(this->m_icont); }
NodeAlloc &node_alloc()
- { return static_cast<NodeAlloc &>(this->members_); }
+ { return static_cast<NodeAlloc &>(*this); }
const NodeAlloc &node_alloc() const
- { return static_cast<const NodeAlloc &>(this->members_); }
-
- members_holder members_;
+ { return static_cast<const NodeAlloc &>(*this); }
public:
ICont &icont()
- { return this->members_.m_icont; }
+ { return this->m_icont; }
const ICont &icont() const
- { return this->members_.m_icont; }
+ { return this->m_icont; }
+
+ private:
+ //The intrusive container
+ ICont m_icont;
};
} //namespace dtl {