adaptive_pool.hpp 23 KB

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