adaptive_pool.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  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_ADAPTIVE_POOL_HPP
  11. #define BOOST_CONTAINER_ADAPTIVE_POOL_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. #include <boost/container/container_fwd.hpp>
  21. #include <boost/container/detail/version_type.hpp>
  22. #include <boost/container/throw_exception.hpp>
  23. #include <boost/container/detail/adaptive_node_pool.hpp>
  24. #include <boost/container/detail/multiallocation_chain.hpp>
  25. #include <boost/container/detail/mpl.hpp>
  26. #include <boost/container/detail/dlmalloc.hpp>
  27. #include <boost/container/detail/singleton.hpp>
  28. #include <boost/container/detail/placement_new.hpp>
  29. #include <boost/assert.hpp>
  30. #include <boost/static_assert.hpp>
  31. #include <boost/move/utility_core.hpp>
  32. #include <cstddef>
  33. namespace boost {
  34. namespace container {
  35. //!An STL node allocator that uses a modified DLMalloc as memory
  36. //!source.
  37. //!
  38. //!This node allocator shares a segregated storage between all instances
  39. //!of adaptive_pool with equal sizeof(T).
  40. //!
  41. //!NodesPerBlock is the number of nodes allocated at once when the allocator
  42. //!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
  43. //!that the adaptive node pool will hold. The rest of the totally free blocks will be
  44. //!deallocated to the memory manager.
  45. //!
  46. //!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
  47. //!(memory usable for nodes / total memory allocated from the memory allocator)
  48. template < class T
  49. , std::size_t NodesPerBlock BOOST_CONTAINER_DOCONLY(= ADP_nodes_per_block)
  50. , std::size_t MaxFreeBlocks BOOST_CONTAINER_DOCONLY(= ADP_max_free_blocks)
  51. , std::size_t OverheadPercent BOOST_CONTAINER_DOCONLY(= ADP_overhead_percent)
  52. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I unsigned Version)
  53. >
  54. class adaptive_pool
  55. {
  56. //!If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
  57. //!the allocator offers advanced expand in place and burst allocation capabilities.
  58. public:
  59. typedef unsigned int allocation_type;
  60. typedef adaptive_pool
  61. <T, NodesPerBlock, MaxFreeBlocks, OverheadPercent
  62. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
  63. > self_t;
  64. static const std::size_t nodes_per_block = NodesPerBlock;
  65. static const std::size_t max_free_blocks = MaxFreeBlocks;
  66. static const std::size_t overhead_percent = OverheadPercent;
  67. static const std::size_t real_nodes_per_block = NodesPerBlock;
  68. BOOST_CONTAINER_DOCIGN(BOOST_STATIC_ASSERT((Version <=2)));
  69. public:
  70. //-------
  71. typedef T value_type;
  72. typedef T * pointer;
  73. typedef const T * const_pointer;
  74. typedef typename ::boost::container::
  75. dtl::unvoid_ref<T>::type reference;
  76. typedef typename ::boost::container::
  77. dtl::unvoid_ref<const T>::type const_reference;
  78. typedef std::size_t size_type;
  79. typedef std::ptrdiff_t difference_type;
  80. typedef boost::container::dtl::
  81. version_type<self_t, Version> version;
  82. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  83. typedef boost::container::dtl::
  84. basic_multiallocation_chain<void*> multiallocation_chain_void;
  85. typedef boost::container::dtl::
  86. transform_multiallocation_chain
  87. <multiallocation_chain_void, T> multiallocation_chain;
  88. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  89. //!Obtains adaptive_pool from
  90. //!adaptive_pool
  91. template<class T2>
  92. struct rebind
  93. {
  94. typedef adaptive_pool
  95. < T2
  96. , NodesPerBlock
  97. , MaxFreeBlocks
  98. , OverheadPercent
  99. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
  100. > other;
  101. };
  102. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  103. private:
  104. //!Not assignable from related adaptive_pool
  105. template<class T2, std::size_t N2, std::size_t F2, std::size_t O2, unsigned Version2>
  106. adaptive_pool& operator=
  107. (const adaptive_pool<T2, N2, F2, O2, Version2>&);
  108. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  109. public:
  110. //!Default constructor
  111. adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW
  112. {}
  113. //!Copy constructor from other adaptive_pool.
  114. adaptive_pool(const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
  115. {}
  116. //!Copy constructor from related adaptive_pool.
  117. template<class T2>
  118. adaptive_pool
  119. (const adaptive_pool<T2, NodesPerBlock, MaxFreeBlocks, OverheadPercent
  120. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)> &) BOOST_NOEXCEPT_OR_NOTHROW
  121. {}
  122. //!Destructor
  123. ~adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW
  124. {}
  125. //!Returns the number of elements that could be allocated.
  126. //!Never throws
  127. size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
  128. { return size_type(-1)/(2u*sizeof(T)); }
  129. //!Allocate memory for an array of count elements.
  130. //!Throws std::bad_alloc if there is no enough memory
  131. pointer allocate(size_type count, const void * = 0)
  132. {
  133. if(BOOST_UNLIKELY(count > size_type(-1)/(2u*sizeof(T))))
  134. boost::container::throw_bad_alloc();
  135. if(Version == 1 && count == 1){
  136. typedef typename dtl::shared_adaptive_node_pool
  137. <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
  138. typedef dtl::singleton_default<shared_pool_t> singleton_t;
  139. return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
  140. }
  141. else{
  142. return static_cast<pointer>(dlmalloc_malloc(count*sizeof(T)));
  143. }
  144. }
  145. //!Deallocate allocated memory.
  146. //!Never throws
  147. void deallocate(const pointer &ptr, size_type count) BOOST_NOEXCEPT_OR_NOTHROW
  148. {
  149. (void)count;
  150. if(Version == 1 && count == 1){
  151. typedef dtl::shared_adaptive_node_pool
  152. <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
  153. typedef dtl::singleton_default<shared_pool_t> singleton_t;
  154. singleton_t::instance().deallocate_node(ptr);
  155. }
  156. else{
  157. dlmalloc_free(ptr);
  158. }
  159. }
  160. pointer allocation_command(allocation_type command,
  161. size_type limit_size,
  162. size_type &prefer_in_recvd_out_size,
  163. pointer &reuse)
  164. {
  165. pointer ret = this->priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
  166. if(BOOST_UNLIKELY(!ret && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION)))
  167. boost::container::throw_bad_alloc();
  168. return ret;
  169. }
  170. //!Returns maximum the number of objects the previously allocated memory
  171. //!pointed by p can hold.
  172. size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
  173. { return dlmalloc_size(p); }
  174. //!Allocates just one object. Memory allocated with this function
  175. //!must be deallocated only with deallocate_one().
  176. //!Throws bad_alloc if there is no enough memory
  177. pointer allocate_one()
  178. {
  179. typedef dtl::shared_adaptive_node_pool
  180. <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
  181. typedef dtl::singleton_default<shared_pool_t> singleton_t;
  182. return (pointer)singleton_t::instance().allocate_node();
  183. }
  184. //!Allocates many elements of size == 1.
  185. //!Elements must be individually deallocated with deallocate_one()
  186. void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
  187. {
  188. typedef dtl::shared_adaptive_node_pool
  189. <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
  190. typedef dtl::singleton_default<shared_pool_t> singleton_t;
  191. singleton_t::instance().allocate_nodes(num_elements, static_cast<typename shared_pool_t::multiallocation_chain&>(chain));
  192. //typename shared_pool_t::multiallocation_chain ch;
  193. //singleton_t::instance().allocate_nodes(num_elements, ch);
  194. //chain.incorporate_after
  195. //(chain.before_begin(), (T*)&*ch.begin(), (T*)&*ch.last(), ch.size());
  196. }
  197. //!Deallocates memory previously allocated with allocate_one().
  198. //!You should never use deallocate_one to deallocate memory allocated
  199. //!with other functions different from allocate_one(). Never throws
  200. void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW
  201. {
  202. typedef dtl::shared_adaptive_node_pool
  203. <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
  204. typedef dtl::singleton_default<shared_pool_t> singleton_t;
  205. singleton_t::instance().deallocate_node(p);
  206. }
  207. void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
  208. {
  209. typedef dtl::shared_adaptive_node_pool
  210. <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
  211. typedef dtl::singleton_default<shared_pool_t> singleton_t;
  212. //typename shared_pool_t::multiallocation_chain ch(&*chain.begin(), &*chain.last(), chain.size());
  213. //singleton_t::instance().deallocate_nodes(ch);
  214. singleton_t::instance().deallocate_nodes(chain);
  215. }
  216. //!Allocates many elements of size elem_size.
  217. //!Elements must be individually deallocated with deallocate()
  218. void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
  219. {
  220. BOOST_STATIC_ASSERT(( Version > 1 ));/*
  221. dlmalloc_memchain ch;
  222. BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
  223. if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){
  224. boost::container::throw_bad_alloc();
  225. }
  226. chain.incorporate_after(chain.before_begin()
  227. ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
  228. ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
  229. ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
  230. if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes
  231. (n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
  232. boost::container::throw_bad_alloc();
  233. }
  234. }
  235. //!Allocates n_elements elements, each one of size elem_sizes[i]
  236. //!Elements must be individually deallocated with deallocate()
  237. void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
  238. {
  239. BOOST_STATIC_ASSERT(( Version > 1 ));/*
  240. dlmalloc_memchain ch;
  241. BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
  242. if(BOOST_UNLIKELY(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){
  243. boost::container::throw_bad_alloc();
  244. }
  245. chain.incorporate_after(chain.before_begin()
  246. ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
  247. ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
  248. ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
  249. if(BOOST_UNLIKELY(!dlmalloc_multialloc_arrays
  250. (n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
  251. boost::container::throw_bad_alloc();
  252. }
  253. }
  254. void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
  255. {/*
  256. dlmalloc_memchain ch;
  257. void *beg(&*chain.begin()), *last(&*chain.last());
  258. size_t size(chain.size());
  259. BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
  260. dlmalloc_multidealloc(&ch);*/
  261. dlmalloc_multidealloc(reinterpret_cast<dlmalloc_memchain *>(&chain));
  262. }
  263. //!Deallocates all free blocks of the pool
  264. static void deallocate_free_blocks() BOOST_NOEXCEPT_OR_NOTHROW
  265. {
  266. typedef dtl::shared_adaptive_node_pool
  267. <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
  268. typedef dtl::singleton_default<shared_pool_t> singleton_t;
  269. singleton_t::instance().deallocate_free_blocks();
  270. }
  271. //!Swaps allocators. Does not throw. If each allocator is placed in a
  272. //!different memory segment, the result is undefined.
  273. friend void swap(adaptive_pool &, adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
  274. {}
  275. //!An allocator always compares to true, as memory allocated with one
  276. //!instance can be deallocated by another instance
  277. friend bool operator==(const adaptive_pool &, const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
  278. { return true; }
  279. //!An allocator always compares to false, as memory allocated with one
  280. //!instance can be deallocated by another instance
  281. friend bool operator!=(const adaptive_pool &, const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
  282. { return false; }
  283. private:
  284. pointer priv_allocation_command
  285. (allocation_type command, std::size_t limit_size
  286. ,size_type &prefer_in_recvd_out_size, pointer &reuse_ptr)
  287. {
  288. std::size_t const preferred_size = prefer_in_recvd_out_size;
  289. dlmalloc_command_ret_t ret = {0 , 0};
  290. if(BOOST_UNLIKELY(limit_size > this->max_size() || preferred_size > this->max_size())){
  291. return pointer();
  292. }
  293. std::size_t l_size = limit_size*sizeof(T);
  294. std::size_t p_size = preferred_size*sizeof(T);
  295. std::size_t r_size;
  296. {
  297. void* reuse_ptr_void = reuse_ptr;
  298. ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
  299. reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
  300. }
  301. prefer_in_recvd_out_size = r_size/sizeof(T);
  302. return (pointer)ret.first;
  303. }
  304. };
  305. template < class T
  306. , std::size_t NodesPerBlock = ADP_nodes_per_block
  307. , std::size_t MaxFreeBlocks = ADP_max_free_blocks
  308. , std::size_t OverheadPercent = ADP_overhead_percent
  309. , unsigned Version = 2
  310. >
  311. class private_adaptive_pool
  312. {
  313. //!If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
  314. //!the allocator offers advanced expand in place and burst allocation capabilities.
  315. public:
  316. typedef unsigned int allocation_type;
  317. typedef private_adaptive_pool
  318. <T, NodesPerBlock, MaxFreeBlocks, OverheadPercent
  319. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
  320. > self_t;
  321. static const std::size_t nodes_per_block = NodesPerBlock;
  322. static const std::size_t max_free_blocks = MaxFreeBlocks;
  323. static const std::size_t overhead_percent = OverheadPercent;
  324. static const std::size_t real_nodes_per_block = NodesPerBlock;
  325. BOOST_CONTAINER_DOCIGN(BOOST_STATIC_ASSERT((Version <=2)));
  326. typedef dtl::private_adaptive_node_pool
  327. <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> pool_t;
  328. pool_t m_pool;
  329. public:
  330. //-------
  331. typedef T value_type;
  332. typedef T * pointer;
  333. typedef const T * const_pointer;
  334. typedef typename ::boost::container::
  335. dtl::unvoid_ref<T>::type reference;
  336. typedef typename ::boost::container::
  337. dtl::unvoid_ref<const T>::type const_reference;
  338. typedef std::size_t size_type;
  339. typedef std::ptrdiff_t difference_type;
  340. typedef boost::container::dtl::
  341. version_type<self_t, Version> version;
  342. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  343. typedef boost::container::dtl::
  344. basic_multiallocation_chain<void*> multiallocation_chain_void;
  345. typedef boost::container::dtl::
  346. transform_multiallocation_chain
  347. <multiallocation_chain_void, T> multiallocation_chain;
  348. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  349. //!Obtains private_adaptive_pool from
  350. //!private_adaptive_pool
  351. template<class T2>
  352. struct rebind
  353. {
  354. typedef private_adaptive_pool
  355. < T2
  356. , NodesPerBlock
  357. , MaxFreeBlocks
  358. , OverheadPercent
  359. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
  360. > other;
  361. };
  362. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  363. private:
  364. //!Not assignable from related private_adaptive_pool
  365. template<class T2, std::size_t N2, std::size_t F2, std::size_t O2, unsigned Version2>
  366. private_adaptive_pool& operator=
  367. (const private_adaptive_pool<T2, N2, F2, O2, Version2>&);
  368. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  369. public:
  370. //!Default constructor
  371. private_adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW
  372. {}
  373. //!Copy constructor from other private_adaptive_pool.
  374. private_adaptive_pool(const private_adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
  375. {}
  376. //!Copy constructor from related private_adaptive_pool.
  377. template<class T2>
  378. private_adaptive_pool
  379. (const private_adaptive_pool<T2, NodesPerBlock, MaxFreeBlocks, OverheadPercent
  380. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)> &) BOOST_NOEXCEPT_OR_NOTHROW
  381. {}
  382. //!Destructor
  383. ~private_adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW
  384. {}
  385. //!Returns the number of elements that could be allocated.
  386. //!Never throws
  387. size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
  388. { return size_type(-1)/(2u*sizeof(T)); }
  389. //!Allocate memory for an array of count elements.
  390. //!Throws std::bad_alloc if there is no enough memory
  391. pointer allocate(size_type count, const void * = 0)
  392. {
  393. if(BOOST_UNLIKELY(count > size_type(-1)/(2u*sizeof(T))))
  394. boost::container::throw_bad_alloc();
  395. if(Version == 1 && count == 1){
  396. return pointer(static_cast<T*>(m_pool.allocate_node()));
  397. }
  398. else{
  399. return static_cast<pointer>(dlmalloc_malloc(count*sizeof(T)));
  400. }
  401. }
  402. //!Deallocate allocated memory.
  403. //!Never throws
  404. void deallocate(const pointer &ptr, size_type count) BOOST_NOEXCEPT_OR_NOTHROW
  405. {
  406. (void)count;
  407. if(Version == 1 && count == 1){
  408. m_pool.deallocate_node(ptr);
  409. }
  410. else{
  411. dlmalloc_free(ptr);
  412. }
  413. }
  414. pointer allocation_command(allocation_type command,
  415. size_type limit_size,
  416. size_type &prefer_in_recvd_out_size,
  417. pointer &reuse)
  418. {
  419. pointer ret = this->priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
  420. if(BOOST_UNLIKELY(!ret && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION)))
  421. boost::container::throw_bad_alloc();
  422. return ret;
  423. }
  424. //!Returns maximum the number of objects the previously allocated memory
  425. //!pointed by p can hold.
  426. size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
  427. { return dlmalloc_size(p); }
  428. //!Allocates just one object. Memory allocated with this function
  429. //!must be deallocated only with deallocate_one().
  430. //!Throws bad_alloc if there is no enough memory
  431. pointer allocate_one()
  432. {
  433. return (pointer)m_pool.allocate_node();
  434. }
  435. //!Allocates many elements of size == 1.
  436. //!Elements must be individually deallocated with deallocate_one()
  437. void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
  438. {
  439. m_pool.allocate_nodes(num_elements, static_cast<typename pool_t::multiallocation_chain&>(chain));
  440. }
  441. //!Deallocates memory previously allocated with allocate_one().
  442. //!You should never use deallocate_one to deallocate memory allocated
  443. //!with other functions different from allocate_one(). Never throws
  444. void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW
  445. {
  446. m_pool.deallocate_node(p);
  447. }
  448. void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
  449. {
  450. m_pool.deallocate_nodes(chain);
  451. }
  452. //!Allocates many elements of size elem_size.
  453. //!Elements must be individually deallocated with deallocate()
  454. void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
  455. {
  456. BOOST_STATIC_ASSERT(( Version > 1 ));
  457. if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes
  458. (n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
  459. boost::container::throw_bad_alloc();
  460. }
  461. }
  462. //!Allocates n_elements elements, each one of size elem_sizes[i]
  463. //!Elements must be individually deallocated with deallocate()
  464. void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
  465. {
  466. BOOST_STATIC_ASSERT(( Version > 1 ));
  467. if(BOOST_UNLIKELY(!dlmalloc_multialloc_arrays
  468. (n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
  469. boost::container::throw_bad_alloc();
  470. }
  471. }
  472. void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
  473. {
  474. dlmalloc_multidealloc(reinterpret_cast<dlmalloc_memchain *>(&chain));
  475. }
  476. //!Deallocates all free blocks of the pool
  477. void deallocate_free_blocks() BOOST_NOEXCEPT_OR_NOTHROW
  478. {
  479. m_pool.deallocate_free_blocks();
  480. }
  481. //!Swaps allocators. Does not throw. If each allocator is placed in a
  482. //!different memory segment, the result is undefined.
  483. friend void swap(private_adaptive_pool &, private_adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
  484. {}
  485. //!An allocator always compares to true, as memory allocated with one
  486. //!instance can be deallocated by another instance
  487. friend bool operator==(const private_adaptive_pool &, const private_adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
  488. { return true; }
  489. //!An allocator always compares to false, as memory allocated with one
  490. //!instance can be deallocated by another instance
  491. friend bool operator!=(const private_adaptive_pool &, const private_adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
  492. { return false; }
  493. private:
  494. pointer priv_allocation_command
  495. (allocation_type command, std::size_t limit_size
  496. ,size_type &prefer_in_recvd_out_size, pointer &reuse_ptr)
  497. {
  498. std::size_t const preferred_size = prefer_in_recvd_out_size;
  499. dlmalloc_command_ret_t ret = {0 , 0};
  500. if(BOOST_UNLIKELY(limit_size > this->max_size() || preferred_size > this->max_size())){
  501. return pointer();
  502. }
  503. std::size_t l_size = limit_size*sizeof(T);
  504. std::size_t p_size = preferred_size*sizeof(T);
  505. std::size_t r_size;
  506. {
  507. void* reuse_ptr_void = reuse_ptr;
  508. ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
  509. reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
  510. }
  511. prefer_in_recvd_out_size = r_size/sizeof(T);
  512. return (pointer)ret.first;
  513. }
  514. };
  515. } //namespace container {
  516. } //namespace boost {
  517. #include <boost/container/detail/config_end.hpp>
  518. #endif //#ifndef BOOST_CONTAINER_ADAPTIVE_POOL_HPP