node_alloc_holder.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
  11. #define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
  12. #ifndef BOOST_CONFIG_HPP
  13. # include <boost/config.hpp>
  14. #endif
  15. #if defined(BOOST_HAS_PRAGMA_ONCE)
  16. # pragma once
  17. #endif
  18. #include <boost/container/detail/config_begin.hpp>
  19. #include <boost/container/detail/workaround.hpp>
  20. // container
  21. #include <boost/container/allocator_traits.hpp>
  22. // container/detail
  23. #include <boost/container/detail/addressof.hpp>
  24. #include <boost/container/detail/alloc_helpers.hpp>
  25. #include <boost/container/detail/allocator_version_traits.hpp>
  26. #include <boost/container/detail/construct_in_place.hpp>
  27. #include <boost/container/detail/destroyers.hpp>
  28. #include <boost/move/detail/iterator_to_raw_pointer.hpp>
  29. #include <boost/container/detail/mpl.hpp>
  30. #include <boost/container/detail/placement_new.hpp>
  31. #include <boost/move/detail/to_raw_pointer.hpp>
  32. #include <boost/container/detail/type_traits.hpp>
  33. #include <boost/container/detail/version_type.hpp>
  34. #include <boost/container/detail/is_pair.hpp>
  35. // intrusive
  36. #include <boost/intrusive/detail/mpl.hpp>
  37. #include <boost/intrusive/options.hpp>
  38. // move
  39. #include <boost/move/utility_core.hpp>
  40. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  41. #include <boost/move/detail/fwd_macros.hpp>
  42. #endif
  43. namespace boost {
  44. namespace container {
  45. //This trait is used to type-pun std::pair because in C++03
  46. //compilers std::pair is useless for C++11 features
  47. template<class T, bool>
  48. struct node_internal_data_type
  49. {
  50. typedef T type;
  51. };
  52. template<class T>
  53. struct node_internal_data_type< T, true>
  54. {
  55. typedef dtl::pair< typename dtl::remove_const<typename T::first_type>::type
  56. , typename T::second_type>
  57. type;
  58. };
  59. template <class T, class HookDefiner, bool PairBased = false>
  60. struct base_node
  61. : public HookDefiner::type
  62. {
  63. public:
  64. typedef T value_type;
  65. typedef typename node_internal_data_type<T, PairBased && dtl::is_pair<T>::value>::type internal_type;
  66. typedef typename HookDefiner::type hook_type;
  67. typedef typename dtl::aligned_storage<sizeof(T), dtl::alignment_of<T>::value>::type storage_t;
  68. storage_t m_storage;
  69. #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000)
  70. #pragma GCC diagnostic push
  71. #pragma GCC diagnostic ignored "-Wstrict-aliasing"
  72. #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING
  73. # endif
  74. public:
  75. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  76. template<class Alloc, class ...Args>
  77. explicit base_node(Alloc &a, Args &&...args)
  78. : hook_type()
  79. {
  80. ::boost::container::allocator_traits<Alloc>::construct
  81. (a, &this->get_real_data(), ::boost::forward<Args>(args)...);
  82. }
  83. #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  84. #define BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL(N) \
  85. template< class Alloc BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
  86. explicit base_node(Alloc &a BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  87. : hook_type()\
  88. {\
  89. ::boost::container::allocator_traits<Alloc>::construct\
  90. (a, &this->get_real_data() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  91. }\
  92. //
  93. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL)
  94. #undef BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL
  95. #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  96. template<class Alloc, class It>
  97. explicit base_node(iterator_arg_t, Alloc &a, It it)
  98. : hook_type()
  99. {
  100. ::boost::container::construct_in_place(a, &this->get_real_data(), it);
  101. }
  102. BOOST_CONTAINER_FORCEINLINE T &get_data()
  103. { return *move_detail::force_ptr<T*>(this->m_storage.data); }
  104. BOOST_CONTAINER_FORCEINLINE const T &get_data() const
  105. { return *move_detail::force_ptr<const T*>(this->m_storage.data); }
  106. BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data()
  107. { return *move_detail::force_ptr<internal_type*>(this->m_storage.data); }
  108. BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const
  109. { return *move_detail::force_ptr<const internal_type*>(this->m_storage.data); }
  110. #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING)
  111. #pragma GCC diagnostic pop
  112. #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING
  113. # endif
  114. template<class Alloc>
  115. BOOST_CONTAINER_FORCEINLINE void destructor(Alloc &a) BOOST_NOEXCEPT
  116. {
  117. allocator_traits<Alloc>::destroy
  118. (a, &this->get_real_data());
  119. this->~base_node();
  120. }
  121. template<class Pair>
  122. BOOST_CONTAINER_FORCEINLINE
  123. typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
  124. do_assign(const Pair &p)
  125. {
  126. typedef typename Pair::first_type first_type;
  127. const_cast<typename dtl::remove_const<first_type>::type &>(this->get_real_data().first) = p.first;
  128. this->get_real_data().second = p.second;
  129. }
  130. template<class V>
  131. BOOST_CONTAINER_FORCEINLINE
  132. typename dtl::disable_if< dtl::is_pair<V>, void >::type
  133. do_assign(const V &v)
  134. { this->get_real_data() = v; }
  135. template<class Pair>
  136. BOOST_CONTAINER_FORCEINLINE
  137. typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
  138. do_move_assign(Pair &p)
  139. {
  140. typedef typename Pair::first_type first_type;
  141. const_cast<first_type&>(this->get_real_data().first) = ::boost::move(p.first);
  142. this->get_real_data().second = ::boost::move(p.second);
  143. }
  144. template<class V>
  145. BOOST_CONTAINER_FORCEINLINE
  146. typename dtl::disable_if< dtl::is_pair<V>, void >::type
  147. do_move_assign(V &v)
  148. { this->get_real_data() = ::boost::move(v); }
  149. private:
  150. base_node();
  151. BOOST_CONTAINER_FORCEINLINE ~base_node()
  152. { }
  153. };
  154. namespace dtl {
  155. BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(key_compare)
  156. BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(key_equal)
  157. BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(hasher)
  158. BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(predicate_type)
  159. BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(bucket_traits)
  160. BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(bucket_type)
  161. template<class Allocator, class ICont>
  162. struct node_alloc_holder
  163. : public allocator_traits<Allocator>::template
  164. portable_rebind_alloc<typename ICont::value_type>::type //NodeAlloc
  165. {
  166. //If the intrusive container is an associative container, obtain the predicate, which will
  167. //be of type node_compare<>. If not an associative container val_compare will be a "nat" type.
  168. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  169. ( boost::container::dtl::
  170. , ICont, key_compare, dtl::nat) intrusive_key_compare;
  171. //If the intrusive container is a hash container, obtain the predicate, which will
  172. //be of type node_compare<>. If not an associative container val_equal will be a "nat" type.
  173. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  174. (boost::container::dtl::
  175. , ICont, key_equal, dtl::nat2) intrusive_val_equal;
  176. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  177. (boost::container::dtl::
  178. , ICont, hasher, dtl::nat3) intrusive_val_hasher;
  179. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  180. (boost::container::dtl::
  181. , ICont, bucket_traits, dtl::natN<0>) intrusive_bucket_traits;
  182. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  183. (boost::container::dtl::
  184. , ICont, bucket_type, dtl::natN<1>) intrusive_bucket_type;
  185. //In that case obtain the value predicate from the node predicate via predicate_type
  186. //if intrusive_key_compare is node_compare<>, nat otherwise
  187. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  188. (boost::container::dtl::
  189. , intrusive_val_equal
  190. , predicate_type, dtl::nat2) val_equal;
  191. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  192. (boost::container::dtl::
  193. , intrusive_val_hasher
  194. , predicate_type, dtl::nat3) val_hasher;
  195. typedef allocator_traits<Allocator> allocator_traits_type;
  196. typedef typename allocator_traits_type::value_type val_type;
  197. typedef ICont intrusive_container;
  198. typedef typename ICont::value_type Node;
  199. typedef typename allocator_traits_type::template
  200. portable_rebind_alloc<Node>::type NodeAlloc;
  201. typedef allocator_traits<NodeAlloc> node_allocator_traits_type;
  202. typedef dtl::allocator_version_traits<NodeAlloc> node_allocator_version_traits_type;
  203. typedef Allocator ValAlloc;
  204. typedef typename node_allocator_traits_type::pointer NodePtr;
  205. typedef dtl::scoped_deallocator<NodeAlloc> Deallocator;
  206. typedef typename node_allocator_traits_type::size_type size_type;
  207. typedef typename node_allocator_traits_type::difference_type difference_type;
  208. typedef dtl::integral_constant<unsigned,
  209. boost::container::dtl::
  210. version<NodeAlloc>::value> alloc_version;
  211. typedef typename ICont::iterator icont_iterator;
  212. typedef typename ICont::const_iterator icont_citerator;
  213. typedef allocator_node_destroyer<NodeAlloc> Destroyer;
  214. typedef allocator_traits<NodeAlloc> NodeAllocTraits;
  215. typedef allocator_version_traits<NodeAlloc> AllocVersionTraits;
  216. private:
  217. BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder)
  218. public:
  219. //Constructors for sequence containers
  220. BOOST_CONTAINER_FORCEINLINE node_alloc_holder()
  221. {}
  222. explicit node_alloc_holder(const intrusive_bucket_traits& bt)
  223. : m_icont(bt)
  224. {}
  225. explicit node_alloc_holder(const ValAlloc &a)
  226. : NodeAlloc(a)
  227. {}
  228. node_alloc_holder(const intrusive_bucket_traits& bt, const ValAlloc& a)
  229. : NodeAlloc(a)
  230. , m_icont(bt)
  231. {}
  232. //Constructors for associative containers
  233. node_alloc_holder(const intrusive_key_compare &c, const ValAlloc &a)
  234. : NodeAlloc(a), m_icont(c)
  235. {}
  236. node_alloc_holder(const intrusive_bucket_traits & bt, const val_hasher &hf, const val_equal &eql, const ValAlloc &a)
  237. : NodeAlloc(a)
  238. , m_icont(bt
  239. , typename ICont::hasher(hf)
  240. , typename ICont::key_equal(eql))
  241. {}
  242. node_alloc_holder(const intrusive_bucket_traits& bt, const val_hasher &hf, const ValAlloc &a)
  243. : NodeAlloc(a)
  244. , m_icont(bt
  245. , typename ICont::hasher(hf)
  246. , typename ICont::key_equal())
  247. {}
  248. node_alloc_holder(const intrusive_bucket_traits& bt, const val_hasher &hf)
  249. : m_icont(bt
  250. , typename ICont::hasher(hf)
  251. , typename ICont::key_equal())
  252. {}
  253. explicit node_alloc_holder(const node_alloc_holder &x)
  254. : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
  255. {}
  256. node_alloc_holder(const node_alloc_holder &x, const intrusive_key_compare &c)
  257. : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
  258. , m_icont(c)
  259. {}
  260. node_alloc_holder(const node_alloc_holder &x, const intrusive_bucket_traits& bt, const val_hasher &hf, const val_equal &eql)
  261. : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
  262. , m_icont( bt
  263. , typename ICont::hasher(hf)
  264. , typename ICont::key_equal(eql))
  265. {}
  266. node_alloc_holder(const val_hasher &hf, const intrusive_bucket_traits& bt, const val_equal &eql)
  267. : m_icont(bt
  268. , typename ICont::hasher(hf)
  269. , typename ICont::key_equal(eql))
  270. {}
  271. explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x)
  272. : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc()))
  273. { this->icont().swap(x.icont()); }
  274. explicit node_alloc_holder(const intrusive_key_compare &c)
  275. : m_icont(c)
  276. {}
  277. //helpers for move assignments
  278. explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const intrusive_key_compare &c)
  279. : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())), m_icont(c)
  280. { this->icont().swap(x.icont()); }
  281. explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const intrusive_bucket_traits& bt, const val_hasher &hf, const val_equal &eql)
  282. : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc()))
  283. , m_icont( bt
  284. , typename ICont::hasher(hf)
  285. , typename ICont::key_equal(eql))
  286. { this->icont().swap(BOOST_MOVE_TO_LV(x).icont()); }
  287. BOOST_CONTAINER_FORCEINLINE void copy_assign_alloc(const node_alloc_holder &x)
  288. {
  289. dtl::bool_<allocator_traits_type::propagate_on_container_copy_assignment::value> flag;
  290. dtl::assign_alloc( static_cast<NodeAlloc &>(*this)
  291. , static_cast<const NodeAlloc &>(x), flag);
  292. }
  293. BOOST_CONTAINER_FORCEINLINE void move_assign_alloc( node_alloc_holder &x)
  294. {
  295. dtl::bool_<allocator_traits_type::propagate_on_container_move_assignment::value> flag;
  296. dtl::move_alloc( static_cast<NodeAlloc &>(*this)
  297. , static_cast<NodeAlloc &>(x), flag);
  298. }
  299. BOOST_CONTAINER_FORCEINLINE ~node_alloc_holder()
  300. { this->clear(alloc_version()); }
  301. BOOST_CONTAINER_FORCEINLINE size_type max_size() const
  302. { return allocator_traits_type::max_size(this->node_alloc()); }
  303. BOOST_CONTAINER_FORCEINLINE NodePtr allocate_one()
  304. { return AllocVersionTraits::allocate_one(this->node_alloc()); }
  305. BOOST_CONTAINER_FORCEINLINE void deallocate_one(const NodePtr &p)
  306. { AllocVersionTraits::deallocate_one(this->node_alloc(), p); }
  307. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  308. template<class ...Args>
  309. NodePtr create_node(Args &&...args)
  310. {
  311. NodePtr p = this->allocate_one();
  312. NodeAlloc &nalloc = this->node_alloc();
  313. Deallocator node_deallocator(p, nalloc);
  314. ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
  315. Node(nalloc, boost::forward<Args>(args)...);
  316. node_deallocator.release();
  317. return (p);
  318. }
  319. #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  320. #define BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL(N) \
  321. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  322. NodePtr create_node(BOOST_MOVE_UREF##N)\
  323. {\
  324. NodePtr p = this->allocate_one();\
  325. NodeAlloc &nalloc = this->node_alloc();\
  326. Deallocator node_deallocator(p, nalloc);\
  327. ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())\
  328. Node(nalloc BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  329. node_deallocator.release();\
  330. return (p);\
  331. }\
  332. //
  333. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL)
  334. #undef BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL
  335. #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  336. template<class It>
  337. NodePtr create_node_from_it(const It &it)
  338. {
  339. NodePtr p = this->allocate_one();
  340. NodeAlloc &nalloc = this->node_alloc();
  341. Deallocator node_deallocator(p, nalloc);
  342. ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
  343. Node(iterator_arg_t(), nalloc, it);
  344. node_deallocator.release();
  345. return (p);
  346. }
  347. template<class KeyConvertible>
  348. NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key)
  349. {
  350. NodePtr p = this->allocate_one();
  351. BOOST_CONTAINER_TRY{
  352. ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;
  353. NodeAlloc &na = this->node_alloc();
  354. node_allocator_traits_type::construct
  355. (na, dtl::addressof(p->get_real_data().first), boost::forward<KeyConvertible>(key));
  356. BOOST_CONTAINER_TRY{
  357. node_allocator_traits_type::construct(na, dtl::addressof(p->get_real_data().second));
  358. }
  359. BOOST_CONTAINER_CATCH(...){
  360. node_allocator_traits_type::destroy(na, dtl::addressof(p->get_real_data().first));
  361. BOOST_CONTAINER_RETHROW;
  362. }
  363. BOOST_CONTAINER_CATCH_END
  364. }
  365. BOOST_CONTAINER_CATCH(...) {
  366. p->destroy_header();
  367. this->node_alloc().deallocate(p, 1);
  368. BOOST_CONTAINER_RETHROW
  369. }
  370. BOOST_CONTAINER_CATCH_END
  371. return (p);
  372. }
  373. void destroy_node(const NodePtr &nodep)
  374. {
  375. boost::movelib::to_raw_pointer(nodep)->destructor(this->node_alloc());
  376. this->deallocate_one(nodep);
  377. }
  378. void swap(node_alloc_holder &x)
  379. {
  380. this->icont().swap(x.icont());
  381. dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
  382. dtl::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
  383. }
  384. template<class FwdIterator, class Inserter>
  385. void allocate_many_and_construct
  386. (FwdIterator beg, size_type n, Inserter inserter)
  387. {
  388. if(n){
  389. typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain_t;
  390. //Try to allocate memory in a single block
  391. typedef typename multiallocation_chain_t::iterator multialloc_iterator_t;
  392. multiallocation_chain_t chain;
  393. NodeAlloc &nalloc = this->node_alloc();
  394. node_allocator_version_traits_type::allocate_individual(nalloc, n, chain);
  395. multialloc_iterator_t itbeg = chain.begin();
  396. multialloc_iterator_t itlast = chain.last();
  397. chain.clear();
  398. Node *p = 0;
  399. BOOST_CONTAINER_TRY{
  400. Deallocator node_deallocator(NodePtr(), nalloc);
  401. dtl::scoped_node_destructor<NodeAlloc> sdestructor(nalloc, 0);
  402. while(n){
  403. --n;
  404. p = boost::movelib::iterator_to_raw_pointer(itbeg);
  405. ++itbeg; //Increment iterator before overwriting pointed memory
  406. //This does not throw
  407. ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
  408. Node(iterator_arg_t(), nalloc, beg);
  409. sdestructor.set(p);
  410. ++beg;
  411. //This can throw in some containers (predicate might throw).
  412. //(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception)
  413. inserter(*p);
  414. sdestructor.release();
  415. }
  416. sdestructor.release();
  417. node_deallocator.release();
  418. }
  419. BOOST_CONTAINER_CATCH(...){
  420. chain.incorporate_after(chain.last(), &*itbeg, &*itlast, n);
  421. node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), chain);
  422. BOOST_CONTAINER_RETHROW
  423. }
  424. BOOST_CONTAINER_CATCH_END
  425. }
  426. }
  427. BOOST_CONTAINER_FORCEINLINE void clear(version_1)
  428. { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); }
  429. void clear(version_2)
  430. {
  431. typename NodeAlloc::multiallocation_chain chain;
  432. allocator_node_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain);
  433. this->icont().clear_and_dispose(builder);
  434. //BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<typename NodeAlloc::multiallocation_chain>::value == true));
  435. if(!chain.empty())
  436. this->node_alloc().deallocate_individual(chain);
  437. }
  438. icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, version_1)
  439. { return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); }
  440. icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, version_2)
  441. {
  442. NodeAlloc & nalloc = this->node_alloc();
  443. typename NodeAlloc::multiallocation_chain chain;
  444. allocator_node_destroyer_and_chain_builder<NodeAlloc> chain_builder(nalloc, chain);
  445. icont_iterator ret_it = this->icont().erase_and_dispose(first, last, chain_builder);
  446. nalloc.deallocate_individual(chain);
  447. return ret_it;
  448. }
  449. template<class Key>
  450. BOOST_CONTAINER_FORCEINLINE size_type erase_key(const Key& k, version_1)
  451. { return this->icont().erase_and_dispose(k, Destroyer(this->node_alloc())); }
  452. template<class Key>
  453. BOOST_CONTAINER_FORCEINLINE size_type erase_key(const Key& k, version_2)
  454. {
  455. allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
  456. return this->icont().erase_and_dispose(k, chain_holder.get_chain_builder());
  457. }
  458. protected:
  459. struct cloner
  460. {
  461. BOOST_CONTAINER_FORCEINLINE explicit cloner(node_alloc_holder &holder)
  462. : m_holder(holder)
  463. {}
  464. BOOST_CONTAINER_FORCEINLINE NodePtr operator()(const Node &other) const
  465. { return m_holder.create_node(other.get_real_data()); }
  466. node_alloc_holder &m_holder;
  467. };
  468. struct move_cloner
  469. {
  470. BOOST_CONTAINER_FORCEINLINE move_cloner(node_alloc_holder &holder)
  471. : m_holder(holder)
  472. {}
  473. BOOST_CONTAINER_FORCEINLINE NodePtr operator()(Node &other)
  474. { //Use get_real_data() instead of get_real_data to allow moving const key in [multi]map
  475. return m_holder.create_node(::boost::move(other.get_real_data()));
  476. }
  477. node_alloc_holder &m_holder;
  478. };
  479. BOOST_CONTAINER_FORCEINLINE ICont &non_const_icont() const
  480. { return const_cast<ICont&>(this->m_icont); }
  481. BOOST_CONTAINER_FORCEINLINE NodeAlloc &node_alloc()
  482. { return static_cast<NodeAlloc &>(*this); }
  483. BOOST_CONTAINER_FORCEINLINE const NodeAlloc &node_alloc() const
  484. { return static_cast<const NodeAlloc &>(*this); }
  485. public:
  486. BOOST_CONTAINER_FORCEINLINE ICont &icont()
  487. { return this->m_icont; }
  488. BOOST_CONTAINER_FORCEINLINE const ICont &icont() const
  489. { return this->m_icont; }
  490. protected:
  491. //The intrusive container
  492. ICont m_icont;
  493. };
  494. template<class Node, class KeyOfValue>
  495. struct key_of_node : KeyOfValue
  496. {
  497. typedef typename KeyOfValue::type type;
  498. BOOST_CONTAINER_FORCEINLINE key_of_node()
  499. {}
  500. BOOST_CONTAINER_FORCEINLINE const type& operator()(const Node& x) const
  501. { return this->KeyOfValue::operator()(x.get_data()); }
  502. };
  503. } //namespace dtl {
  504. } //namespace container {
  505. } //namespace boost {
  506. #include <boost/container/detail/config_end.hpp>
  507. #endif // BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_