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

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