adaptive_pool.hpp 24 KB

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