/Src/Dependencies/Boost/boost/interprocess/allocators/adaptive_pool.hpp

http://hadesmem.googlecode.com/ · C++ Header · 466 lines · 250 code · 77 blank · 139 comment · 3 complexity · 83b3807714c1118d806fe707279cdb23 MD5 · raw file

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/interprocess for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP
  11. #define BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP
  12. #if (defined _MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif
  15. #include <boost/interprocess/detail/config_begin.hpp>
  16. #include <boost/interprocess/detail/workaround.hpp>
  17. #include <boost/pointer_to_other.hpp>
  18. #include <boost/interprocess/interprocess_fwd.hpp>
  19. #include <boost/assert.hpp>
  20. #include <boost/utility/addressof.hpp>
  21. #include <boost/interprocess/detail/utilities.hpp>
  22. #include <boost/interprocess/detail/type_traits.hpp>
  23. #include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
  24. #include <boost/interprocess/exceptions.hpp>
  25. #include <boost/interprocess/allocators/detail/allocator_common.hpp>
  26. #include <boost/interprocess/containers/container/detail/multiallocation_chain.hpp>
  27. #include <boost/interprocess/detail/mpl.hpp>
  28. #include <memory>
  29. #include <algorithm>
  30. #include <cstddef>
  31. //!\file
  32. //!Describes adaptive_pool pooled shared memory STL compatible allocator
  33. namespace boost {
  34. namespace interprocess {
  35. /// @cond
  36. namespace detail{
  37. template < unsigned int Version
  38. , class T
  39. , class SegmentManager
  40. , std::size_t NodesPerBlock
  41. , std::size_t MaxFreeBlocks
  42. , unsigned char OverheadPercent
  43. >
  44. class adaptive_pool_base
  45. : public node_pool_allocation_impl
  46. < adaptive_pool_base
  47. < Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
  48. , Version
  49. , T
  50. , SegmentManager
  51. >
  52. {
  53. public:
  54. typedef typename SegmentManager::void_pointer void_pointer;
  55. typedef SegmentManager segment_manager;
  56. typedef adaptive_pool_base
  57. <Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> self_t;
  58. /// @cond
  59. template <int dummy>
  60. struct node_pool
  61. {
  62. typedef detail::shared_adaptive_node_pool
  63. < SegmentManager, sizeof_value<T>::value, NodesPerBlock, MaxFreeBlocks, OverheadPercent> type;
  64. static type *get(void *p)
  65. { return static_cast<type*>(p); }
  66. };
  67. /// @endcond
  68. BOOST_STATIC_ASSERT((Version <=2));
  69. public:
  70. //-------
  71. typedef typename boost::
  72. pointer_to_other<void_pointer, T>::type pointer;
  73. typedef typename boost::
  74. pointer_to_other<void_pointer, const T>::type const_pointer;
  75. typedef T value_type;
  76. typedef typename detail::add_reference
  77. <value_type>::type reference;
  78. typedef typename detail::add_reference
  79. <const value_type>::type const_reference;
  80. typedef std::size_t size_type;
  81. typedef std::ptrdiff_t difference_type;
  82. typedef boost::interprocess::version_type<adaptive_pool_base, Version> version;
  83. typedef boost::container::containers_detail::transform_multiallocation_chain
  84. <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
  85. //!Obtains adaptive_pool_base from
  86. //!adaptive_pool_base
  87. template<class T2>
  88. struct rebind
  89. {
  90. typedef adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
  91. };
  92. /// @cond
  93. private:
  94. //!Not assignable from related adaptive_pool_base
  95. template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char O2>
  96. adaptive_pool_base& operator=
  97. (const adaptive_pool_base<Version2, T2, SegmentManager2, N2, F2, O2>&);
  98. /// @endcond
  99. public:
  100. //!Constructor from a segment manager. If not present, constructs a node
  101. //!pool. Increments the reference count of the associated node pool.
  102. //!Can throw boost::interprocess::bad_alloc
  103. adaptive_pool_base(segment_manager *segment_mngr)
  104. : mp_node_pool(detail::get_or_create_node_pool<typename node_pool<0>::type>(segment_mngr)) { }
  105. //!Copy constructor from other adaptive_pool_base. Increments the reference
  106. //!count of the associated node pool. Never throws
  107. adaptive_pool_base(const adaptive_pool_base &other)
  108. : mp_node_pool(other.get_node_pool())
  109. {
  110. node_pool<0>::get(detail::get_pointer(mp_node_pool))->inc_ref_count();
  111. }
  112. //!Assignment from other adaptive_pool_base
  113. adaptive_pool_base& operator=(const adaptive_pool_base &other)
  114. {
  115. adaptive_pool_base c(other);
  116. swap(*this, c);
  117. return *this;
  118. }
  119. //!Copy constructor from related adaptive_pool_base. If not present, constructs
  120. //!a node pool. Increments the reference count of the associated node pool.
  121. //!Can throw boost::interprocess::bad_alloc
  122. template<class T2>
  123. adaptive_pool_base
  124. (const adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
  125. : mp_node_pool(detail::get_or_create_node_pool<typename node_pool<0>::type>(other.get_segment_manager())) { }
  126. //!Destructor, removes node_pool_t from memory
  127. //!if its reference count reaches to zero. Never throws
  128. ~adaptive_pool_base()
  129. { detail::destroy_node_pool_if_last_link(node_pool<0>::get(detail::get_pointer(mp_node_pool))); }
  130. //!Returns a pointer to the node pool.
  131. //!Never throws
  132. void* get_node_pool() const
  133. { return detail::get_pointer(mp_node_pool); }
  134. //!Returns the segment manager.
  135. //!Never throws
  136. segment_manager* get_segment_manager()const
  137. { return node_pool<0>::get(detail::get_pointer(mp_node_pool))->get_segment_manager(); }
  138. //!Swaps allocators. Does not throw. If each allocator is placed in a
  139. //!different memory segment, the result is undefined.
  140. friend void swap(self_t &alloc1, self_t &alloc2)
  141. { detail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); }
  142. /// @cond
  143. private:
  144. void_pointer mp_node_pool;
  145. /// @endcond
  146. };
  147. //!Equality test for same type
  148. //!of adaptive_pool_base
  149. template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
  150. bool operator==(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
  151. const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
  152. { return alloc1.get_node_pool() == alloc2.get_node_pool(); }
  153. //!Inequality test for same type
  154. //!of adaptive_pool_base
  155. template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
  156. bool operator!=(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
  157. const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
  158. { return alloc1.get_node_pool() != alloc2.get_node_pool(); }
  159. template < class T
  160. , class SegmentManager
  161. , std::size_t NodesPerBlock = 64
  162. , std::size_t MaxFreeBlocks = 2
  163. , unsigned char OverheadPercent = 5
  164. >
  165. class adaptive_pool_v1
  166. : public adaptive_pool_base
  167. < 1
  168. , T
  169. , SegmentManager
  170. , NodesPerBlock
  171. , MaxFreeBlocks
  172. , OverheadPercent
  173. >
  174. {
  175. public:
  176. typedef detail::adaptive_pool_base
  177. < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
  178. template<class T2>
  179. struct rebind
  180. {
  181. typedef adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
  182. };
  183. adaptive_pool_v1(SegmentManager *segment_mngr)
  184. : base_t(segment_mngr)
  185. {}
  186. template<class T2>
  187. adaptive_pool_v1
  188. (const adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
  189. : base_t(other)
  190. {}
  191. };
  192. } //namespace detail{
  193. /// @endcond
  194. //!An STL node allocator that uses a segment manager as memory
  195. //!source. The internal pointer type will of the same type (raw, smart) as
  196. //!"typename SegmentManager::void_pointer" type. This allows
  197. //!placing the allocator in shared memory, memory mapped-files, etc...
  198. //!
  199. //!This node allocator shares a segregated storage between all instances
  200. //!of adaptive_pool with equal sizeof(T) placed in the same segment
  201. //!group. NodesPerBlock is the number of nodes allocated at once when the allocator
  202. //!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
  203. //!that the adaptive node pool will hold. The rest of the totally free blocks will be
  204. //!deallocated with the segment manager.
  205. //!
  206. //!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
  207. //!(memory usable for nodes / total memory allocated from the segment manager)
  208. template < class T
  209. , class SegmentManager
  210. , std::size_t NodesPerBlock
  211. , std::size_t MaxFreeBlocks
  212. , unsigned char OverheadPercent
  213. >
  214. class adaptive_pool
  215. /// @cond
  216. : public detail::adaptive_pool_base
  217. < 2
  218. , T
  219. , SegmentManager
  220. , NodesPerBlock
  221. , MaxFreeBlocks
  222. , OverheadPercent
  223. >
  224. /// @endcond
  225. {
  226. #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  227. typedef detail::adaptive_pool_base
  228. < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
  229. public:
  230. typedef boost::interprocess::version_type<adaptive_pool, 2> version;
  231. template<class T2>
  232. struct rebind
  233. {
  234. typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
  235. };
  236. adaptive_pool(SegmentManager *segment_mngr)
  237. : base_t(segment_mngr)
  238. {}
  239. template<class T2>
  240. adaptive_pool
  241. (const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
  242. : base_t(other)
  243. {}
  244. #else //BOOST_INTERPROCESS_DOXYGEN_INVOKED
  245. public:
  246. typedef implementation_defined::segment_manager segment_manager;
  247. typedef segment_manager::void_pointer void_pointer;
  248. typedef implementation_defined::pointer pointer;
  249. typedef implementation_defined::const_pointer const_pointer;
  250. typedef T value_type;
  251. typedef typename detail::add_reference
  252. <value_type>::type reference;
  253. typedef typename detail::add_reference
  254. <const value_type>::type const_reference;
  255. typedef std::size_t size_type;
  256. typedef std::ptrdiff_t difference_type;
  257. //!Obtains adaptive_pool from
  258. //!adaptive_pool
  259. template<class T2>
  260. struct rebind
  261. {
  262. typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
  263. };
  264. private:
  265. //!Not assignable from
  266. //!related adaptive_pool
  267. template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
  268. adaptive_pool& operator=
  269. (const adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&);
  270. //!Not assignable from
  271. //!other adaptive_pool
  272. //adaptive_pool& operator=(const adaptive_pool&);
  273. public:
  274. //!Constructor from a segment manager. If not present, constructs a node
  275. //!pool. Increments the reference count of the associated node pool.
  276. //!Can throw boost::interprocess::bad_alloc
  277. adaptive_pool(segment_manager *segment_mngr);
  278. //!Copy constructor from other adaptive_pool. Increments the reference
  279. //!count of the associated node pool. Never throws
  280. adaptive_pool(const adaptive_pool &other);
  281. //!Copy constructor from related adaptive_pool. If not present, constructs
  282. //!a node pool. Increments the reference count of the associated node pool.
  283. //!Can throw boost::interprocess::bad_alloc
  284. template<class T2>
  285. adaptive_pool
  286. (const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other);
  287. //!Destructor, removes node_pool_t from memory
  288. //!if its reference count reaches to zero. Never throws
  289. ~adaptive_pool();
  290. //!Returns a pointer to the node pool.
  291. //!Never throws
  292. void* get_node_pool() const;
  293. //!Returns the segment manager.
  294. //!Never throws
  295. segment_manager* get_segment_manager()const;
  296. //!Returns the number of elements that could be allocated.
  297. //!Never throws
  298. size_type max_size() const;
  299. //!Allocate memory for an array of count elements.
  300. //!Throws boost::interprocess::bad_alloc if there is no enough memory
  301. pointer allocate(size_type count, cvoid_pointer hint = 0);
  302. //!Deallocate allocated memory.
  303. //!Never throws
  304. void deallocate(const pointer &ptr, size_type count);
  305. //!Deallocates all free blocks
  306. //!of the pool
  307. void deallocate_free_blocks();
  308. //!Swaps allocators. Does not throw. If each allocator is placed in a
  309. //!different memory segment, the result is undefined.
  310. friend void swap(self_t &alloc1, self_t &alloc2);
  311. //!Returns address of mutable object.
  312. //!Never throws
  313. pointer address(reference value) const;
  314. //!Returns address of non mutable object.
  315. //!Never throws
  316. const_pointer address(const_reference value) const;
  317. //!Copy construct an object.
  318. //!Throws if T's copy constructor throws
  319. void construct(const pointer &ptr, const_reference v);
  320. //!Destroys object. Throws if object's
  321. //!destructor throws
  322. void destroy(const pointer &ptr);
  323. //!Returns maximum the number of objects the previously allocated memory
  324. //!pointed by p can hold. This size only works for memory allocated with
  325. //!allocate, allocation_command and allocate_many.
  326. size_type size(const pointer &p) const;
  327. std::pair<pointer, bool>
  328. allocation_command(boost::interprocess::allocation_type command,
  329. size_type limit_size,
  330. size_type preferred_size,
  331. size_type &received_size, const pointer &reuse = 0);
  332. //!Allocates many elements of size elem_size in a contiguous block
  333. //!of memory. The minimum number to be allocated is min_elements,
  334. //!the preferred and maximum number is
  335. //!preferred_elements. The number of actually allocated elements is
  336. //!will be assigned to received_size. The elements must be deallocated
  337. //!with deallocate(...)
  338. multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
  339. //!Allocates n_elements elements, each one of size elem_sizes[i]in a
  340. //!contiguous block
  341. //!of memory. The elements must be deallocated
  342. multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
  343. //!Allocates many elements of size elem_size in a contiguous block
  344. //!of memory. The minimum number to be allocated is min_elements,
  345. //!the preferred and maximum number is
  346. //!preferred_elements. The number of actually allocated elements is
  347. //!will be assigned to received_size. The elements must be deallocated
  348. //!with deallocate(...)
  349. void deallocate_many(multiallocation_chain chain);
  350. //!Allocates just one object. Memory allocated with this function
  351. //!must be deallocated only with deallocate_one().
  352. //!Throws boost::interprocess::bad_alloc if there is no enough memory
  353. pointer allocate_one();
  354. //!Allocates many elements of size == 1 in a contiguous block
  355. //!of memory. The minimum number to be allocated is min_elements,
  356. //!the preferred and maximum number is
  357. //!preferred_elements. The number of actually allocated elements is
  358. //!will be assigned to received_size. Memory allocated with this function
  359. //!must be deallocated only with deallocate_one().
  360. multiallocation_chain allocate_individual(std::size_t num_elements);
  361. //!Deallocates memory previously allocated with allocate_one().
  362. //!You should never use deallocate_one to deallocate memory allocated
  363. //!with other functions different from allocate_one(). Never throws
  364. void deallocate_one(const pointer &p);
  365. //!Allocates many elements of size == 1 in a contiguous block
  366. //!of memory. The minimum number to be allocated is min_elements,
  367. //!the preferred and maximum number is
  368. //!preferred_elements. The number of actually allocated elements is
  369. //!will be assigned to received_size. Memory allocated with this function
  370. //!must be deallocated only with deallocate_one().
  371. void deallocate_individual(multiallocation_chain it);
  372. #endif
  373. };
  374. #ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  375. //!Equality test for same type
  376. //!of adaptive_pool
  377. template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
  378. bool operator==(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
  379. const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
  380. //!Inequality test for same type
  381. //!of adaptive_pool
  382. template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
  383. bool operator!=(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
  384. const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
  385. #endif
  386. } //namespace interprocess {
  387. } //namespace boost {
  388. #include <boost/interprocess/detail/config_end.hpp>
  389. #endif //#ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP