annotate DEPENDENCIES/generic/include/boost/pool/object_pool.hpp @ 133:4acb5d8d80b6 tip

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