|
|
|||
File indexing completed on 2025-12-16 10:05:02
0001 // Copyright (C) 2000, 2001 Stephen Cleary 0002 // 0003 // Distributed under the Boost Software License, Version 1.0. (See 0004 // accompanying file LICENSE_1_0.txt or copy at 0005 // http://www.boost.org/LICENSE_1_0.txt) 0006 // 0007 // See http://www.boost.org for updates, documentation, and revision history. 0008 0009 #ifndef BOOST_OBJECT_POOL_HPP 0010 #define BOOST_OBJECT_POOL_HPP 0011 /*! 0012 \file 0013 \brief Provides a template type boost::object_pool<T, UserAllocator> 0014 that can be used for fast and efficient memory allocation of objects of type T. 0015 It also provides automatic destruction of non-deallocated objects. 0016 */ 0017 0018 #include <boost/pool/poolfwd.hpp> 0019 0020 // boost::pool 0021 #include <boost/pool/pool.hpp> 0022 0023 // The following code will be put into Boost.Config in a later revision 0024 #if defined(BOOST_MSVC) || defined(__KCC) 0025 # define BOOST_NO_TEMPLATE_CV_REF_OVERLOADS 0026 #endif 0027 0028 // The following code might be put into some Boost.Config header in a later revision 0029 #ifdef BOOST_BORLANDC 0030 # pragma option push -w-inl 0031 #endif 0032 0033 // There are a few places in this file where the expression "this->m" is used. 0034 // This expression is used to force instantiation-time name lookup, which I am 0035 // informed is required for strict Standard compliance. It's only necessary 0036 // if "m" is a member of a base class that is dependent on a template 0037 // parameter. 0038 // Thanks to Jens Maurer for pointing this out! 0039 0040 namespace boost { 0041 0042 /*! \brief A template class 0043 that can be used for fast and efficient memory allocation of objects. 0044 It also provides automatic destruction of non-deallocated objects. 0045 0046 \details 0047 0048 <b>T</b> The type of object to allocate/deallocate. 0049 T must have a non-throwing destructor. 0050 0051 <b>UserAllocator</b> 0052 Defines the allocator that the underlying Pool will use to allocate memory from the system. 0053 See <a href="boost_pool/pool/pooling.html#boost_pool.pool.pooling.user_allocator">User Allocators</a> for details. 0054 0055 Class object_pool is a template class 0056 that can be used for fast and efficient memory allocation of objects. 0057 It also provides automatic destruction of non-deallocated objects. 0058 0059 When the object pool is destroyed, then the destructor for type T 0060 is called for each allocated T that has not yet been deallocated. O(N). 0061 0062 Whenever an object of type ObjectPool needs memory from the system, 0063 it will request it from its UserAllocator template parameter. 0064 The amount requested is determined using a doubling algorithm; 0065 that is, each time more system memory is allocated, 0066 the amount of system memory requested is doubled. 0067 Users may control the doubling algorithm by the parameters passed 0068 to the object_pool's constructor. 0069 */ 0070 0071 template <typename T, typename UserAllocator> 0072 class object_pool: protected pool<UserAllocator> 0073 { //! 0074 public: 0075 typedef T element_type; //!< ElementType 0076 typedef UserAllocator user_allocator; //!< 0077 typedef typename pool<UserAllocator>::size_type size_type; //!< pool<UserAllocator>::size_type 0078 typedef typename pool<UserAllocator>::difference_type difference_type; //!< pool<UserAllocator>::difference_type 0079 0080 protected: 0081 //! \return The underlying boost:: \ref pool storage used by *this. 0082 pool<UserAllocator> & store() 0083 { 0084 return *this; 0085 } 0086 //! \return The underlying boost:: \ref pool storage used by *this. 0087 const pool<UserAllocator> & store() const 0088 { 0089 return *this; 0090 } 0091 0092 // for the sake of code readability :) 0093 static void * & nextof(void * const ptr) 0094 { //! \returns The next memory block after ptr (for the sake of code readability :) 0095 return *(static_cast<void **>(ptr)); 0096 } 0097 0098 public: 0099 explicit object_pool(const size_type arg_next_size = 32, const size_type arg_max_size = 0) 0100 : 0101 pool<UserAllocator>(sizeof(T), arg_next_size, arg_max_size) 0102 { //! Constructs a new (empty by default) ObjectPool. 0103 //! \param next_size Number of chunks to request from the system the next time that object needs to allocate system memory (default 32). 0104 //! \pre next_size != 0. 0105 //! \param max_size Maximum number of chunks to ever request from the system - this puts a cap on the doubling algorithm 0106 //! used by the underlying pool. 0107 } 0108 0109 ~object_pool(); 0110 0111 // Returns 0 if out-of-memory. 0112 element_type * malloc BOOST_PREVENT_MACRO_SUBSTITUTION() 0113 { //! Allocates memory that can hold one object of type ElementType. 0114 //! 0115 //! If out of memory, returns 0. 0116 //! 0117 //! Amortized O(1). 0118 return static_cast<element_type *>(store().ordered_malloc()); 0119 } 0120 void free BOOST_PREVENT_MACRO_SUBSTITUTION(element_type * const chunk) 0121 { //! De-Allocates memory that holds a chunk of type ElementType. 0122 //! 0123 //! Note that p may not be 0.\n 0124 //! 0125 //! Note that the destructor for p is not called. O(N). 0126 store().ordered_free(chunk); 0127 } 0128 bool is_from(element_type * const chunk) const 0129 { /*! \returns true if chunk was allocated from *this or 0130 may be returned as the result of a future allocation from *this. 0131 0132 Returns false if chunk was allocated from some other pool or 0133 may be returned as the result of a future allocation from some other pool. 0134 0135 Otherwise, the return value is meaningless. 0136 0137 \note This function may NOT be used to reliably test random pointer values! 0138 */ 0139 return store().is_from(chunk); 0140 } 0141 0142 element_type * construct() 0143 { //! \returns A pointer to an object of type T, allocated in memory from the underlying pool 0144 //! and default constructed. The returned objected can be freed by a call to \ref destroy. 0145 //! Otherwise the returned object will be automatically destroyed when *this is destroyed. 0146 element_type * const ret = (malloc)(); 0147 if (ret == 0) 0148 return ret; 0149 try { new (ret) element_type(); } 0150 catch (...) { (free)(ret); throw; } 0151 return ret; 0152 } 0153 0154 0155 #if defined(BOOST_DOXYGEN) 0156 template <class Arg1, ... class ArgN> 0157 element_type * construct(Arg1&, ... ArgN&) 0158 { 0159 //! \returns A pointer to an object of type T, allocated in memory from the underlying pool 0160 //! and constructed from arguments Arg1 to ArgN. The returned objected can be freed by a call to \ref destroy. 0161 //! Otherwise the returned object will be automatically destroyed when *this is destroyed. 0162 //! 0163 //! \note Since the number and type of arguments to this function is totally arbitrary, a simple system has been 0164 //! set up to automatically generate template construct functions. This system is based on the macro preprocessor 0165 //! m4, which is standard on UNIX systems and also available for Win32 systems.\n\n 0166 //! detail/pool_construct.m4, when run with m4, will create the file detail/pool_construct.ipp, which only defines 0167 //! the construct functions for the proper number of arguments. The number of arguments may be passed into the 0168 //! file as an m4 macro, NumberOfArguments; if not provided, it will default to 3.\n\n 0169 //! For each different number of arguments (1 to NumberOfArguments), a template function is generated. There 0170 //! are the same number of template parameters as there are arguments, and each argument's type is a reference 0171 //! to that (possibly cv-qualified) template argument. Each possible permutation of the cv-qualifications is also generated.\n\n 0172 //! Because each permutation is generated for each possible number of arguments, the included file size grows 0173 //! exponentially in terms of the number of constructor arguments, not linearly. For the sake of rational 0174 //! compile times, only use as many arguments as you need.\n\n 0175 //! detail/pool_construct.bat and detail/pool_construct.sh are also provided to call m4, defining NumberOfArguments 0176 //! to be their command-line parameter. See these files for more details. 0177 } 0178 #else 0179 // Include automatically-generated file for family of template construct() functions. 0180 // Copy .inc renamed .ipp to conform to Doxygen include filename expectations, PAB 12 Jan 11. 0181 // But still get Doxygen warning: 0182 // I:/boost-sandbox/guild/pool/boost/pool/object_pool.hpp:82: 0183 // Warning: include file boost/pool/detail/pool_construct.ipp 0184 // not found, perhaps you forgot to add its directory to INCLUDE_PATH? 0185 // But the file IS found and referenced OK, but cannot view code. 0186 // This seems because not at the head of the file 0187 // But if moved this up, Doxygen is happy, but of course it won't compile, 0188 // because the many constructors *must* go here. 0189 0190 #ifndef BOOST_NO_TEMPLATE_CV_REF_OVERLOADS 0191 # include <boost/pool/detail/pool_construct.ipp> 0192 #else 0193 # include <boost/pool/detail/pool_construct_simple.ipp> 0194 #endif 0195 #endif 0196 void destroy(element_type * const chunk) 0197 { //! Destroys an object allocated with \ref construct. 0198 //! 0199 //! Equivalent to: 0200 //! 0201 //! p->~ElementType(); this->free(p); 0202 //! 0203 //! \pre p must have been previously allocated from *this via a call to \ref construct. 0204 chunk->~T(); 0205 (free)(chunk); 0206 } 0207 0208 size_type get_next_size() const 0209 { //! \returns The number of chunks that will be allocated next time we run out of memory. 0210 return store().get_next_size(); 0211 } 0212 void set_next_size(const size_type x) 0213 { //! Set a new number of chunks to allocate the next time we run out of memory. 0214 //! \param x wanted next_size (must not be zero). 0215 store().set_next_size(x); 0216 } 0217 }; 0218 0219 template <typename T, typename UserAllocator> 0220 object_pool<T, UserAllocator>::~object_pool() 0221 { 0222 #ifndef BOOST_POOL_VALGRIND 0223 // handle trivial case of invalid list. 0224 if (!this->list.valid()) 0225 return; 0226 0227 details::PODptr<size_type> iter = this->list; 0228 details::PODptr<size_type> next = iter; 0229 0230 // Start 'freed_iter' at beginning of free list 0231 void * freed_iter = this->first; 0232 0233 const size_type partition_size = this->alloc_size(); 0234 0235 do 0236 { 0237 // increment next 0238 next = next.next(); 0239 0240 // delete all contained objects that aren't freed. 0241 0242 // Iterate 'i' through all chunks in the memory block. 0243 for (char * i = iter.begin(); i != iter.end(); i += partition_size) 0244 { 0245 // If this chunk is free, 0246 if (i == freed_iter) 0247 { 0248 // Increment freed_iter to point to next in free list. 0249 freed_iter = nextof(freed_iter); 0250 0251 // Continue searching chunks in the memory block. 0252 continue; 0253 } 0254 0255 // This chunk is not free (allocated), so call its destructor, 0256 static_cast<T *>(static_cast<void *>(i))->~T(); 0257 // and continue searching chunks in the memory block. 0258 } 0259 0260 // free storage. 0261 (UserAllocator::free)(iter.begin()); 0262 0263 // increment iter. 0264 iter = next; 0265 } while (iter.valid()); 0266 0267 // Make the block list empty so that the inherited destructor doesn't try to 0268 // free it again. 0269 this->list.invalidate(); 0270 #else 0271 // destruct all used elements: 0272 for(std::set<void*>::iterator pos = this->used_list.begin(); pos != this->used_list.end(); ++pos) 0273 { 0274 static_cast<T*>(*pos)->~T(); 0275 } 0276 // base class will actually free the memory... 0277 #endif 0278 } 0279 0280 } // namespace boost 0281 0282 // The following code might be put into some Boost.Config header in a later revision 0283 #ifdef BOOST_BORLANDC 0284 # pragma option pop 0285 #endif 0286 0287 #endif
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|