object_pool.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // Copyright (C) 2000, 2001 Stephen Cleary
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org for updates, documentation, and revision history.
  8. #ifndef BOOST_OBJECT_POOL_HPP
  9. #define BOOST_OBJECT_POOL_HPP
  10. /*!
  11. \file
  12. \brief Provides a template type boost::object_pool<T, UserAllocator>
  13. that can be used for fast and efficient memory allocation of objects of type T.
  14. It also provides automatic destruction of non-deallocated objects.
  15. */
  16. #include <boost/pool/poolfwd.hpp>
  17. // boost::pool
  18. #include <boost/pool/pool.hpp>
  19. // The following code will be put into Boost.Config in a later revision
  20. #if defined(BOOST_MSVC) || defined(__KCC)
  21. # define BOOST_NO_TEMPLATE_CV_REF_OVERLOADS
  22. #endif
  23. // The following code might be put into some Boost.Config header in a later revision
  24. #ifdef BOOST_BORLANDC
  25. # pragma option push -w-inl
  26. #endif
  27. // There are a few places in this file where the expression "this->m" is used.
  28. // This expression is used to force instantiation-time name lookup, which I am
  29. // informed is required for strict Standard compliance. It's only necessary
  30. // if "m" is a member of a base class that is dependent on a template
  31. // parameter.
  32. // Thanks to Jens Maurer for pointing this out!
  33. namespace boost {
  34. /*! \brief A template class
  35. that can be used for fast and efficient memory allocation of objects.
  36. It also provides automatic destruction of non-deallocated objects.
  37. \details
  38. <b>T</b> The type of object to allocate/deallocate.
  39. T must have a non-throwing destructor.
  40. <b>UserAllocator</b>
  41. Defines the allocator that the underlying Pool will use to allocate memory from the system.
  42. See <a href="boost_pool/pool/pooling.html#boost_pool.pool.pooling.user_allocator">User Allocators</a> for details.
  43. Class object_pool is a template class
  44. that can be used for fast and efficient memory allocation of objects.
  45. It also provides automatic destruction of non-deallocated objects.
  46. When the object pool is destroyed, then the destructor for type T
  47. is called for each allocated T that has not yet been deallocated. O(N).
  48. Whenever an object of type ObjectPool needs memory from the system,
  49. it will request it from its UserAllocator template parameter.
  50. The amount requested is determined using a doubling algorithm;
  51. that is, each time more system memory is allocated,
  52. the amount of system memory requested is doubled.
  53. Users may control the doubling algorithm by the parameters passed
  54. to the object_pool's constructor.
  55. */
  56. template <typename T, typename UserAllocator>
  57. class object_pool: protected pool<UserAllocator>
  58. { //!
  59. public:
  60. typedef T element_type; //!< ElementType
  61. typedef UserAllocator user_allocator; //!<
  62. typedef typename pool<UserAllocator>::size_type size_type; //!< pool<UserAllocator>::size_type
  63. typedef typename pool<UserAllocator>::difference_type difference_type; //!< pool<UserAllocator>::difference_type
  64. protected:
  65. //! \return The underlying boost:: \ref pool storage used by *this.
  66. pool<UserAllocator> & store()
  67. {
  68. return *this;
  69. }
  70. //! \return The underlying boost:: \ref pool storage used by *this.
  71. const pool<UserAllocator> & store() const
  72. {
  73. return *this;
  74. }
  75. // for the sake of code readability :)
  76. static void * & nextof(void * const ptr)
  77. { //! \returns The next memory block after ptr (for the sake of code readability :)
  78. return *(static_cast<void **>(ptr));
  79. }
  80. public:
  81. explicit object_pool(const size_type arg_next_size = 32, const size_type arg_max_size = 0)
  82. :
  83. pool<UserAllocator>(sizeof(T), arg_next_size, arg_max_size)
  84. { //! Constructs a new (empty by default) ObjectPool.
  85. //! \param next_size Number of chunks to request from the system the next time that object needs to allocate system memory (default 32).
  86. //! \pre next_size != 0.
  87. //! \param max_size Maximum number of chunks to ever request from the system - this puts a cap on the doubling algorithm
  88. //! used by the underlying pool.
  89. }
  90. ~object_pool();
  91. // Returns 0 if out-of-memory.
  92. element_type * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
  93. { //! Allocates memory that can hold one object of type ElementType.
  94. //!
  95. //! If out of memory, returns 0.
  96. //!
  97. //! Amortized O(1).
  98. return static_cast<element_type *>(store().ordered_malloc());
  99. }
  100. void free BOOST_PREVENT_MACRO_SUBSTITUTION(element_type * const chunk)
  101. { //! De-Allocates memory that holds a chunk of type ElementType.
  102. //!
  103. //! Note that p may not be 0.\n
  104. //!
  105. //! Note that the destructor for p is not called. O(N).
  106. store().ordered_free(chunk);
  107. }
  108. bool is_from(element_type * const chunk) const
  109. { /*! \returns true if chunk was allocated from *this or
  110. may be returned as the result of a future allocation from *this.
  111. Returns false if chunk was allocated from some other pool or
  112. may be returned as the result of a future allocation from some other pool.
  113. Otherwise, the return value is meaningless.
  114. \note This function may NOT be used to reliably test random pointer values!
  115. */
  116. return store().is_from(chunk);
  117. }
  118. element_type * construct()
  119. { //! \returns A pointer to an object of type T, allocated in memory from the underlying pool
  120. //! and default constructed. The returned objected can be freed by a call to \ref destroy.
  121. //! Otherwise the returned object will be automatically destroyed when *this is destroyed.
  122. element_type * const ret = (malloc)();
  123. if (ret == 0)
  124. return ret;
  125. try { new (ret) element_type(); }
  126. catch (...) { (free)(ret); throw; }
  127. return ret;
  128. }
  129. #if defined(BOOST_DOXYGEN)
  130. template <class Arg1, ... class ArgN>
  131. element_type * construct(Arg1&, ... ArgN&)
  132. {
  133. //! \returns A pointer to an object of type T, allocated in memory from the underlying pool
  134. //! and constructed from arguments Arg1 to ArgN. The returned objected can be freed by a call to \ref destroy.
  135. //! Otherwise the returned object will be automatically destroyed when *this is destroyed.
  136. //!
  137. //! \note Since the number and type of arguments to this function is totally arbitrary, a simple system has been
  138. //! set up to automatically generate template construct functions. This system is based on the macro preprocessor
  139. //! m4, which is standard on UNIX systems and also available for Win32 systems.\n\n
  140. //! detail/pool_construct.m4, when run with m4, will create the file detail/pool_construct.ipp, which only defines
  141. //! the construct functions for the proper number of arguments. The number of arguments may be passed into the
  142. //! file as an m4 macro, NumberOfArguments; if not provided, it will default to 3.\n\n
  143. //! For each different number of arguments (1 to NumberOfArguments), a template function is generated. There
  144. //! are the same number of template parameters as there are arguments, and each argument's type is a reference
  145. //! to that (possibly cv-qualified) template argument. Each possible permutation of the cv-qualifications is also generated.\n\n
  146. //! Because each permutation is generated for each possible number of arguments, the included file size grows
  147. //! exponentially in terms of the number of constructor arguments, not linearly. For the sake of rational
  148. //! compile times, only use as many arguments as you need.\n\n
  149. //! detail/pool_construct.bat and detail/pool_construct.sh are also provided to call m4, defining NumberOfArguments
  150. //! to be their command-line parameter. See these files for more details.
  151. }
  152. #else
  153. // Include automatically-generated file for family of template construct() functions.
  154. // Copy .inc renamed .ipp to conform to Doxygen include filename expectations, PAB 12 Jan 11.
  155. // But still get Doxygen warning:
  156. // I:/boost-sandbox/guild/pool/boost/pool/object_pool.hpp:82:
  157. // Warning: include file boost/pool/detail/pool_construct.ipp
  158. // not found, perhaps you forgot to add its directory to INCLUDE_PATH?
  159. // But the file IS found and referenced OK, but cannot view code.
  160. // This seems because not at the head of the file
  161. // But if moved this up, Doxygen is happy, but of course it won't compile,
  162. // because the many constructors *must* go here.
  163. #ifndef BOOST_NO_TEMPLATE_CV_REF_OVERLOADS
  164. # include <boost/pool/detail/pool_construct.ipp>
  165. #else
  166. # include <boost/pool/detail/pool_construct_simple.ipp>
  167. #endif
  168. #endif
  169. void destroy(element_type * const chunk)
  170. { //! Destroys an object allocated with \ref construct.
  171. //!
  172. //! Equivalent to:
  173. //!
  174. //! p->~ElementType(); this->free(p);
  175. //!
  176. //! \pre p must have been previously allocated from *this via a call to \ref construct.
  177. chunk->~T();
  178. (free)(chunk);
  179. }
  180. size_type get_next_size() const
  181. { //! \returns The number of chunks that will be allocated next time we run out of memory.
  182. return store().get_next_size();
  183. }
  184. void set_next_size(const size_type x)
  185. { //! Set a new number of chunks to allocate the next time we run out of memory.
  186. //! \param x wanted next_size (must not be zero).
  187. store().set_next_size(x);
  188. }
  189. };
  190. template <typename T, typename UserAllocator>
  191. object_pool<T, UserAllocator>::~object_pool()
  192. {
  193. #ifndef BOOST_POOL_VALGRIND
  194. // handle trivial case of invalid list.
  195. if (!this->list.valid())
  196. return;
  197. details::PODptr<size_type> iter = this->list;
  198. details::PODptr<size_type> next = iter;
  199. // Start 'freed_iter' at beginning of free list
  200. void * freed_iter = this->first;
  201. const size_type partition_size = this->alloc_size();
  202. do
  203. {
  204. // increment next
  205. next = next.next();
  206. // delete all contained objects that aren't freed.
  207. // Iterate 'i' through all chunks in the memory block.
  208. for (char * i = iter.begin(); i != iter.end(); i += partition_size)
  209. {
  210. // If this chunk is free,
  211. if (i == freed_iter)
  212. {
  213. // Increment freed_iter to point to next in free list.
  214. freed_iter = nextof(freed_iter);
  215. // Continue searching chunks in the memory block.
  216. continue;
  217. }
  218. // This chunk is not free (allocated), so call its destructor,
  219. static_cast<T *>(static_cast<void *>(i))->~T();
  220. // and continue searching chunks in the memory block.
  221. }
  222. // free storage.
  223. (UserAllocator::free)(iter.begin());
  224. // increment iter.
  225. iter = next;
  226. } while (iter.valid());
  227. // Make the block list empty so that the inherited destructor doesn't try to
  228. // free it again.
  229. this->list.invalidate();
  230. #else
  231. // destruct all used elements:
  232. for(std::set<void*>::iterator pos = this->used_list.begin(); pos != this->used_list.end(); ++pos)
  233. {
  234. static_cast<T*>(*pos)->~T();
  235. }
  236. // base class will actually free the memory...
  237. #endif
  238. }
  239. } // namespace boost
  240. // The following code might be put into some Boost.Config header in a later revision
  241. #ifdef BOOST_BORLANDC
  242. # pragma option pop
  243. #endif
  244. #endif