adaptive_pool.hpp 23 KB

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