Back to home page

EIC code displayed by LXR

 
 

    


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