/Src/Dependencies/Boost/boost/interprocess/containers/container/detail/node_alloc_holder.hpp

http://hadesmem.googlecode.com/ · C++ Header · 501 lines · 382 code · 100 blank · 19 comment · 10 complexity · 7100dabc29478b7ce1612767676588e7 MD5 · raw file

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2009. 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_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
  11. #define BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
  12. #if (defined _MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif
  15. #include "config_begin.hpp"
  16. #include INCLUDE_BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
  17. #include <utility>
  18. #include <functional>
  19. #include INCLUDE_BOOST_CONTAINER_MOVE_HPP
  20. #include <boost/intrusive/options.hpp>
  21. #include INCLUDE_BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
  22. #include INCLUDE_BOOST_CONTAINER_DETAIL_TYPE_TRAITS_HPP
  23. #include INCLUDE_BOOST_CONTAINER_DETAIL_UTILITIES_HPP
  24. #include INCLUDE_BOOST_CONTAINER_DETAIL_MPL_HPP
  25. #include INCLUDE_BOOST_CONTAINER_DETAIL_DESTROYERS_HPP
  26. #ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
  27. #include INCLUDE_BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP
  28. #endif
  29. #include INCLUDE_BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
  30. namespace boost {
  31. namespace container {
  32. namespace containers_detail {
  33. //!A deleter for scoped_ptr that deallocates the memory
  34. //!allocated for an object using a STL allocator.
  35. template <class Allocator>
  36. struct scoped_deallocator
  37. {
  38. typedef typename Allocator::pointer pointer;
  39. typedef containers_detail::integral_constant<unsigned,
  40. boost::container::containers_detail::
  41. version<Allocator>::value> alloc_version;
  42. typedef containers_detail::integral_constant<unsigned, 1> allocator_v1;
  43. typedef containers_detail::integral_constant<unsigned, 2> allocator_v2;
  44. private:
  45. void priv_deallocate(allocator_v1)
  46. { m_alloc.deallocate(m_ptr, 1); }
  47. void priv_deallocate(allocator_v2)
  48. { m_alloc.deallocate_one(m_ptr); }
  49. BOOST_MOVE_MACRO_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
  50. public:
  51. pointer m_ptr;
  52. Allocator& m_alloc;
  53. scoped_deallocator(pointer p, Allocator& a)
  54. : m_ptr(p), m_alloc(a)
  55. {}
  56. ~scoped_deallocator()
  57. { if (m_ptr)priv_deallocate(alloc_version()); }
  58. scoped_deallocator(BOOST_MOVE_MACRO_RV_REF(scoped_deallocator) o)
  59. : m_ptr(o.m_ptr), m_alloc(o.m_alloc)
  60. { o.release(); }
  61. pointer get() const
  62. { return m_ptr; }
  63. void release()
  64. { m_ptr = 0; }
  65. };
  66. template <class A>
  67. class allocator_destroyer_and_chain_builder
  68. {
  69. typedef typename A::value_type value_type;
  70. typedef typename A::multiallocation_chain multiallocation_chain;
  71. A & a_;
  72. multiallocation_chain &c_;
  73. public:
  74. allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
  75. : a_(a), c_(c)
  76. {}
  77. void operator()(const typename A::pointer &p)
  78. {
  79. value_type *vp = containers_detail::get_pointer(p);
  80. vp->~value_type();
  81. c_.push_front(vp);
  82. }
  83. };
  84. template <class A>
  85. class allocator_multialloc_chain_node_deallocator
  86. {
  87. typedef typename A::value_type value_type;
  88. typedef typename A::multiallocation_chain multiallocation_chain;
  89. typedef allocator_destroyer_and_chain_builder<A> chain_builder;
  90. A & a_;
  91. multiallocation_chain c_;
  92. public:
  93. allocator_multialloc_chain_node_deallocator(A &a)
  94. : a_(a), c_()
  95. {}
  96. chain_builder get_chain_builder()
  97. { return chain_builder(a_, c_); }
  98. ~allocator_multialloc_chain_node_deallocator()
  99. {
  100. if(!c_.empty())
  101. a_.deallocate_individual(BOOST_CONTAINER_MOVE_NAMESPACE::move(c_));
  102. }
  103. };
  104. template<class ValueCompare, class Node>
  105. struct node_compare
  106. : private ValueCompare
  107. {
  108. typedef typename ValueCompare::key_type key_type;
  109. typedef typename ValueCompare::value_type value_type;
  110. typedef typename ValueCompare::key_of_value key_of_value;
  111. node_compare(const ValueCompare &pred)
  112. : ValueCompare(pred)
  113. {}
  114. ValueCompare &value_comp()
  115. { return static_cast<ValueCompare &>(*this); }
  116. ValueCompare &value_comp() const
  117. { return static_cast<const ValueCompare &>(*this); }
  118. bool operator()(const Node &a, const Node &b) const
  119. { return ValueCompare::operator()(a.get_data(), b.get_data()); }
  120. };
  121. template<class A, class ICont>
  122. struct node_alloc_holder
  123. {
  124. typedef node_alloc_holder<A, ICont> self_t;
  125. typedef typename A::value_type value_type;
  126. typedef typename ICont::value_type Node;
  127. typedef typename A::template rebind<Node>::other NodeAlloc;
  128. typedef A ValAlloc;
  129. typedef typename NodeAlloc::pointer NodePtr;
  130. typedef containers_detail::scoped_deallocator<NodeAlloc> Deallocator;
  131. typedef typename NodeAlloc::size_type size_type;
  132. typedef typename NodeAlloc::difference_type difference_type;
  133. typedef containers_detail::integral_constant<unsigned, 1> allocator_v1;
  134. typedef containers_detail::integral_constant<unsigned, 2> allocator_v2;
  135. typedef containers_detail::integral_constant<unsigned,
  136. boost::container::containers_detail::
  137. version<NodeAlloc>::value> alloc_version;
  138. typedef typename ICont::iterator icont_iterator;
  139. typedef typename ICont::const_iterator icont_citerator;
  140. typedef allocator_destroyer<NodeAlloc> Destroyer;
  141. private:
  142. BOOST_MOVE_MACRO_COPYABLE_AND_MOVABLE(node_alloc_holder)
  143. public:
  144. node_alloc_holder(const ValAlloc &a)
  145. : members_(a)
  146. {}
  147. node_alloc_holder(const node_alloc_holder &other)
  148. : members_(other.node_alloc())
  149. {}
  150. node_alloc_holder(BOOST_MOVE_MACRO_RV_REF(node_alloc_holder) other)
  151. : members_(BOOST_CONTAINER_MOVE_NAMESPACE::move(other.node_alloc()))
  152. { this->swap(other); }
  153. node_alloc_holder & operator=(BOOST_MOVE_MACRO_COPY_ASSIGN_REF(node_alloc_holder) other)
  154. { members_.assign(other.node_alloc()); }
  155. node_alloc_holder & operator=(BOOST_MOVE_MACRO_RV_REF(node_alloc_holder) other)
  156. { members_.assign(other.node_alloc()); }
  157. template<class Pred>
  158. node_alloc_holder(const ValAlloc &a, const Pred &c)
  159. : members_(a, typename ICont::value_compare(c))
  160. {}
  161. template<class Pred>
  162. node_alloc_holder(BOOST_MOVE_MACRO_RV_REF(ValAlloc) a, const Pred &c)
  163. : members_(a, typename ICont::value_compare(c))
  164. {}
  165. template<class Pred>
  166. node_alloc_holder(const node_alloc_holder &other, const Pred &c)
  167. : members_(other.node_alloc(), typename ICont::value_compare(c))
  168. {}
  169. ~node_alloc_holder()
  170. { this->clear(alloc_version()); }
  171. size_type max_size() const
  172. { return this->node_alloc().max_size(); }
  173. NodePtr allocate_one()
  174. { return this->allocate_one(alloc_version()); }
  175. NodePtr allocate_one(allocator_v1)
  176. { return this->node_alloc().allocate(1); }
  177. NodePtr allocate_one(allocator_v2)
  178. { return this->node_alloc().allocate_one(); }
  179. void deallocate_one(NodePtr p)
  180. { return this->deallocate_one(p, alloc_version()); }
  181. void deallocate_one(NodePtr p, allocator_v1)
  182. { this->node_alloc().deallocate(p, 1); }
  183. void deallocate_one(NodePtr p, allocator_v2)
  184. { this->node_alloc().deallocate_one(p); }
  185. template<class Convertible1, class Convertible2>
  186. static void construct(const NodePtr &ptr,
  187. BOOST_MOVE_MACRO_RV_REF_2_TEMPL_ARGS(std::pair, Convertible1, Convertible2) value)
  188. {
  189. typedef typename Node::hook_type hook_type;
  190. typedef typename Node::value_type::first_type first_type;
  191. typedef typename Node::value_type::second_type second_type;
  192. Node *nodeptr = containers_detail::get_pointer(ptr);
  193. //Hook constructor does not throw
  194. new(static_cast<hook_type*>(nodeptr))hook_type();
  195. //Now construct pair members_holder
  196. value_type *valueptr = &nodeptr->get_data();
  197. new((void*)&valueptr->first) first_type(BOOST_CONTAINER_MOVE_NAMESPACE::move(value.first));
  198. BOOST_TRY{
  199. new((void*)&valueptr->second) second_type(BOOST_CONTAINER_MOVE_NAMESPACE::move(value.second));
  200. }
  201. BOOST_CATCH(...){
  202. valueptr->first.~first_type();
  203. static_cast<hook_type*>(nodeptr)->~hook_type();
  204. BOOST_RETHROW
  205. }
  206. BOOST_CATCH_END
  207. }
  208. static void destroy(const NodePtr &ptr)
  209. { containers_detail::get_pointer(ptr)->~Node(); }
  210. Deallocator create_node_and_deallocator()
  211. {
  212. return Deallocator(this->allocate_one(), this->node_alloc());
  213. }
  214. #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
  215. template<class ...Args>
  216. static void construct(const NodePtr &ptr, Args &&...args)
  217. { new((void*)containers_detail::get_pointer(ptr)) Node(BOOST_CONTAINER_MOVE_NAMESPACE::forward<Args>(args)...); }
  218. template<class ...Args>
  219. NodePtr create_node(Args &&...args)
  220. {
  221. NodePtr p = this->allocate_one();
  222. Deallocator node_deallocator(p, this->node_alloc());
  223. self_t::construct(p, BOOST_CONTAINER_MOVE_NAMESPACE::forward<Args>(args)...);
  224. node_deallocator.release();
  225. return (p);
  226. }
  227. #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
  228. static void construct(const NodePtr &ptr)
  229. { new((void*)containers_detail::get_pointer(ptr)) Node(); }
  230. NodePtr create_node()
  231. {
  232. NodePtr p = this->allocate_one();
  233. Deallocator node_deallocator(p, this->node_alloc());
  234. self_t::construct(p);
  235. node_deallocator.release();
  236. return (p);
  237. }
  238. #define BOOST_PP_LOCAL_MACRO(n) \
  239. template<BOOST_PP_ENUM_PARAMS(n, class P)> \
  240. void construct(const NodePtr &ptr, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
  241. { \
  242. new((void*)containers_detail::get_pointer(ptr)) \
  243. Node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
  244. } \
  245. //!
  246. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
  247. #include BOOST_PP_LOCAL_ITERATE()
  248. #define BOOST_PP_LOCAL_MACRO(n) \
  249. template<BOOST_PP_ENUM_PARAMS(n, class P)> \
  250. NodePtr create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
  251. { \
  252. NodePtr p = this->allocate_one(); \
  253. Deallocator node_deallocator(p, this->node_alloc()); \
  254. self_t::construct(p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
  255. node_deallocator.release(); \
  256. return (p); \
  257. } \
  258. //!
  259. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
  260. #include BOOST_PP_LOCAL_ITERATE()
  261. #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
  262. template<class It>
  263. NodePtr create_node_from_it(It it)
  264. {
  265. NodePtr p = this->allocate_one();
  266. Deallocator node_deallocator(p, this->node_alloc());
  267. ::boost::container::construct_in_place(containers_detail::get_pointer(p), it);
  268. node_deallocator.release();
  269. return (p);
  270. }
  271. void destroy_node(NodePtr node)
  272. {
  273. self_t::destroy(node);
  274. this->deallocate_one(node);
  275. }
  276. void swap(node_alloc_holder &x)
  277. {
  278. NodeAlloc& this_alloc = this->node_alloc();
  279. NodeAlloc& other_alloc = x.node_alloc();
  280. if (this_alloc != other_alloc){
  281. containers_detail::do_swap(this_alloc, other_alloc);
  282. }
  283. this->icont().swap(x.icont());
  284. }
  285. template<class FwdIterator, class Inserter>
  286. FwdIterator allocate_many_and_construct
  287. (FwdIterator beg, difference_type n, Inserter inserter)
  288. {
  289. if(n){
  290. typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
  291. //Try to allocate memory in a single block
  292. multiallocation_chain mem(this->node_alloc().allocate_individual(n));
  293. int constructed = 0;
  294. Node *p = 0;
  295. BOOST_TRY{
  296. for(difference_type i = 0; i < n; ++i, ++beg, --constructed){
  297. p = containers_detail::get_pointer(mem.front());
  298. mem.pop_front();
  299. //This can throw
  300. constructed = 0;
  301. boost::container::construct_in_place(p, beg);
  302. ++constructed;
  303. //This can throw in some containers (predicate might throw)
  304. inserter(*p);
  305. }
  306. }
  307. BOOST_CATCH(...){
  308. if(constructed){
  309. this->destroy(p);
  310. }
  311. this->node_alloc().deallocate_individual(BOOST_CONTAINER_MOVE_NAMESPACE::move(mem));
  312. BOOST_RETHROW
  313. }
  314. BOOST_CATCH_END
  315. }
  316. return beg;
  317. }
  318. void clear(allocator_v1)
  319. { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); }
  320. void clear(allocator_v2)
  321. {
  322. typename NodeAlloc::multiallocation_chain chain;
  323. allocator_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain);
  324. this->icont().clear_and_dispose(builder);
  325. BOOST_STATIC_ASSERT((::BOOST_CONTAINER_MOVE_NAMESPACE::is_movable<typename NodeAlloc::multiallocation_chain>::value == true));
  326. if(!chain.empty())
  327. this->node_alloc().deallocate_individual(BOOST_CONTAINER_MOVE_NAMESPACE::move(chain));
  328. }
  329. icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v1)
  330. { return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); }
  331. icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v2)
  332. {
  333. allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
  334. return this->icont().erase_and_dispose(first, last, chain_holder.get_chain_builder());
  335. }
  336. template<class Key, class Comparator>
  337. size_type erase_key(const Key& k, const Comparator &comp, allocator_v1)
  338. { return this->icont().erase_and_dispose(k, comp, Destroyer(this->node_alloc())); }
  339. template<class Key, class Comparator>
  340. size_type erase_key(const Key& k, const Comparator &comp, allocator_v2)
  341. {
  342. allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
  343. return this->icont().erase_and_dispose(k, comp, chain_holder.get_chain_builder());
  344. }
  345. protected:
  346. struct cloner
  347. {
  348. cloner(node_alloc_holder &holder)
  349. : m_holder(holder)
  350. {}
  351. NodePtr operator()(const Node &other) const
  352. { return m_holder.create_node(other.get_data()); }
  353. node_alloc_holder &m_holder;
  354. };
  355. struct destroyer
  356. {
  357. destroyer(node_alloc_holder &holder)
  358. : m_holder(holder)
  359. {}
  360. void operator()(NodePtr n) const
  361. { m_holder.destroy_node(n); }
  362. node_alloc_holder &m_holder;
  363. };
  364. struct members_holder
  365. : public NodeAlloc
  366. {
  367. private:
  368. members_holder(const members_holder&);
  369. public:
  370. template<class ConvertibleToAlloc>
  371. members_holder(const ConvertibleToAlloc &c2alloc)
  372. : NodeAlloc(c2alloc)
  373. {}
  374. template<class ConvertibleToAlloc, class Pred>
  375. members_holder(const ConvertibleToAlloc &c2alloc, const Pred &c)
  376. : NodeAlloc(c2alloc), m_icont(c)
  377. {}
  378. template<class ConvertibleToAlloc>
  379. void assign (const ConvertibleToAlloc &c2alloc)
  380. {
  381. NodeAlloc::operator=(c2alloc);
  382. }
  383. //The intrusive container
  384. ICont m_icont;
  385. } members_;
  386. ICont &non_const_icont() const
  387. { return const_cast<ICont&>(this->members_.m_icont); }
  388. ICont &icont()
  389. { return this->members_.m_icont; }
  390. const ICont &icont() const
  391. { return this->members_.m_icont; }
  392. NodeAlloc &node_alloc()
  393. { return static_cast<NodeAlloc &>(this->members_); }
  394. const NodeAlloc &node_alloc() const
  395. { return static_cast<const NodeAlloc &>(this->members_); }
  396. };
  397. } //namespace containers_detail {
  398. } //namespace container {
  399. } //namespace boost {
  400. #include INCLUDE_BOOST_CONTAINER_DETAIL_CONFIG_END_HPP
  401. #endif // BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_