Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:26:34

0001 // Copyright (C) 2000, 2001 Stephen Cleary
0002 // Copyright (C) 2010 Paul A. Bristow added Doxygen comments.
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See
0005 // accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 // See http://www.boost.org for updates, documentation, and revision history.
0009 
0010 #ifndef BOOST_POOL_ALLOC_HPP
0011 #define BOOST_POOL_ALLOC_HPP
0012 
0013 /*!
0014   \file
0015   \brief C++ Standard Library compatible pool-based allocators.
0016   \details  This header provides two template types - 
0017   \ref pool_allocator and \ref fast_pool_allocator -
0018   that can be used for fast and efficient memory allocation
0019   in conjunction with the C++ Standard Library containers.
0020 
0021   These types both satisfy the Standard Allocator requirements [20.1.5]
0022   and the additional requirements in [20.1.5/4],
0023   so they can be used with either Standard or user-supplied containers.
0024 
0025   In addition, the fast_pool_allocator also provides an additional allocation
0026   and an additional deallocation function:
0027 
0028 <table>
0029 <tr><th>Expression</th><th>Return Type</th><th>Semantic Equivalence<th></tr>
0030 <tr><td><tt>PoolAlloc::allocate()</tt></td><td><tt>T *</tt></td><td><tt>PoolAlloc::allocate(1)</tt></tr>
0031 <tr><td><tt>PoolAlloc::deallocate(p)</tt></td><td>void</tt></td><td><tt>PoolAlloc::deallocate(p, 1)</tt></tr>
0032 </table>
0033 
0034 The typedef user_allocator publishes the value of the UserAllocator template parameter.
0035 
0036 <b>Notes</b>
0037 
0038 If the allocation functions run out of memory, they will throw <tt>std::bad_alloc</tt>.
0039 
0040 The underlying Pool type used by the allocators is accessible through the Singleton Pool Interface.
0041 The identifying tag used for pool_allocator is pool_allocator_tag,
0042 and the tag used for fast_pool_allocator is fast_pool_allocator_tag.
0043 All template parameters of the allocators (including implementation-specific ones)
0044 determine the type of the underlying Pool,
0045 with the exception of the first parameter T, whose size is used instead.
0046 
0047 Since the size of T is used to determine the type of the underlying Pool,
0048 each allocator for different types of the same size will share the same underlying pool.
0049 The tag class prevents pools from being shared between pool_allocator and fast_pool_allocator.
0050 For example, on a system where
0051 <tt>sizeof(int) == sizeof(void *)</tt>, <tt>pool_allocator<int></tt> and <tt>pool_allocator<void *></tt>
0052 will both allocate/deallocate from/to the same pool.
0053 
0054 If there is only one thread running before main() starts and after main() ends,
0055 then both allocators are completely thread-safe.
0056 
0057 <b>Compiler and STL Notes</b>
0058 
0059 A number of common STL libraries contain bugs in their using of allocators.
0060 Specifically, they pass null pointers to the deallocate function,
0061 which is explicitly forbidden by the Standard [20.1.5 Table 32].
0062 PoolAlloc will work around these libraries if it detects them;
0063 currently, workarounds are in place for:
0064 Borland C++ (Builder and command-line compiler)
0065 with default (RogueWave) library, ver. 5 and earlier,
0066 STLport (with any compiler), ver. 4.0 and earlier.
0067 */
0068 
0069 // std::numeric_limits
0070 #include <boost/limits.hpp>
0071 // new, std::bad_alloc
0072 #include <new>
0073 
0074 #include <boost/throw_exception.hpp>
0075 #include <boost/pool/poolfwd.hpp>
0076 
0077 // boost::singleton_pool
0078 #include <boost/pool/singleton_pool.hpp>
0079 
0080 #include <boost/detail/workaround.hpp>
0081 
0082 // C++11 features detection
0083 #include <boost/config.hpp>
0084 
0085 // std::forward
0086 #ifdef BOOST_HAS_VARIADIC_TMPL
0087 #include <utility>
0088 #endif
0089 
0090 #ifdef BOOST_POOL_INSTRUMENT
0091 #include <iostream>
0092 #include <iomanip>
0093 #endif
0094 
0095 // The following code will be put into Boost.Config in a later revision
0096 #if defined(_RWSTD_VER) || defined(__SGI_STL_PORT) || \
0097     BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x582))
0098  #define BOOST_NO_PROPER_STL_DEALLOCATE
0099 #endif
0100 
0101 namespace boost {
0102 
0103 #ifdef BOOST_POOL_INSTRUMENT
0104 
0105 template <bool b>
0106 struct debug_info
0107 {
0108    static unsigned allocated;
0109 };
0110 
0111 template <bool b>
0112 unsigned debug_info<b>::allocated = 0;
0113 
0114 #endif
0115 
0116  //! Simple tag type used by pool_allocator as an argument to the
0117  //! underlying singleton_pool.
0118  struct pool_allocator_tag
0119 {
0120 };
0121 
0122 /*!  \brief A C++ Standard Library conforming allocator, based on an underlying pool.
0123 
0124   Template parameters for pool_allocator are defined as follows:
0125 
0126   <b>T</b> Type of object to allocate/deallocate.
0127 
0128   <b>UserAllocator</B>. Defines the method that the underlying Pool will use to allocate memory from the system. See 
0129   <a href="boost_pool/pool/pooling.html#boost_pool.pool.pooling.user_allocator">User Allocators</a> for details.
0130 
0131   <b>Mutex</b> Allows the user to determine the type of synchronization to be used on the underlying singleton_pool. 
0132 
0133   <b>NextSize</b> The value of this parameter is passed to the underlying singleton_pool when it is created.
0134 
0135   <b>MaxSize</b> Limit on the maximum size used.
0136 
0137   \attention
0138   The underlying singleton_pool used by the this allocator
0139   constructs a pool instance that
0140   <b>is never freed</b>.  This means that memory allocated
0141   by the allocator can be still used after main() has
0142   completed, but may mean that some memory checking programs
0143   will complain about leaks.
0144  
0145   
0146   */
0147 template <typename T,
0148     typename UserAllocator,
0149     typename Mutex,
0150     unsigned NextSize,
0151     unsigned MaxSize >
0152 class pool_allocator
0153 {
0154   public:
0155     typedef T value_type;  //!< value_type of template parameter T.
0156     typedef UserAllocator user_allocator;  //!< allocator that defines the method that the underlying Pool will use to allocate memory from the system.
0157     typedef Mutex mutex; //!< typedef mutex publishes the value of the template parameter Mutex.
0158     BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize); //!< next_size publishes the values of the template parameter NextSize.
0159 
0160     typedef value_type * pointer; //!<
0161     typedef const value_type * const_pointer;
0162     typedef value_type & reference;
0163     typedef const value_type & const_reference;
0164     typedef typename pool<UserAllocator>::size_type size_type;
0165     typedef typename pool<UserAllocator>::difference_type difference_type;
0166 
0167     //! \brief Nested class rebind allows for transformation from
0168     //! pool_allocator<T> to pool_allocator<U>.
0169     //!
0170     //! Nested class rebind allows for transformation from
0171     //! pool_allocator<T> to pool_allocator<U> via the member
0172     //! typedef other.
0173     template <typename U>
0174     struct rebind
0175     { //
0176       typedef pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
0177     };
0178 
0179   public:
0180     pool_allocator()
0181     { /*! Results in default construction of the underlying singleton_pool IFF an
0182        instance of this allocator is constructed during global initialization (
0183          required to ensure construction of singleton_pool IFF an
0184          instance of this allocator is constructed during global
0185          initialization. See ticket #2359 for a complete explanation at
0186          http://svn.boost.org/trac/boost/ticket/2359) .
0187        */
0188       singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
0189                      NextSize, MaxSize>::is_from(0);
0190     }
0191 
0192     // default copy constructor.
0193 
0194     // default assignment operator.
0195 
0196     // not explicit, mimicking std::allocator [20.4.1]
0197     template <typename U>
0198     pool_allocator(const pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> &)
0199     { /*! Results in the default construction of the underlying singleton_pool, this
0200          is required to ensure construction of singleton_pool IFF an
0201          instance of this allocator is constructed during global
0202          initialization. See ticket #2359 for a complete explanation
0203          at http://svn.boost.org/trac/boost/ticket/2359 .
0204        */
0205       singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
0206                      NextSize, MaxSize>::is_from(0);
0207     }
0208 
0209     // default destructor
0210 
0211     static pointer address(reference r)
0212     { return &r; }
0213     static const_pointer address(const_reference s)
0214     { return &s; }
0215     static size_type max_size()
0216     { return (std::numeric_limits<size_type>::max)(); }
0217 
0218 #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
0219     template <typename U, typename... Args>
0220     static void construct(U* ptr, Args&&... args)
0221     { new (ptr) U(std::forward<Args>(args)...); }
0222 #else
0223     static void construct(const pointer ptr, const value_type & t)
0224     { new (ptr) T(t); }
0225 #endif
0226 
0227     static void destroy(const pointer ptr)
0228     {
0229       ptr->~T();
0230       (void) ptr; // avoid unused variable warning.
0231     }
0232 
0233     bool operator==(const pool_allocator &) const
0234     { return true; }
0235     bool operator!=(const pool_allocator &) const
0236     { return false; }
0237 
0238     static pointer allocate(const size_type n)
0239     {
0240 #ifdef BOOST_POOL_INSTRUMENT
0241        debug_info<true>::allocated += n * sizeof(T);
0242        std::cout << "Allocating " << n << " * " << sizeof(T) << " bytes...\n"
0243           "Total allocated is now " << debug_info<true>::allocated << std::endl;
0244 #endif
0245       const pointer ret = static_cast<pointer>(
0246           singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
0247               NextSize, MaxSize>::ordered_malloc(n) );
0248       if ((ret == 0) && n)
0249         boost::throw_exception(std::bad_alloc());
0250       return ret;
0251     }
0252     static pointer allocate(const size_type n, const void * const)
0253     { //! allocate n bytes
0254     //! \param n bytes to allocate.
0255     //! \param unused.
0256       return allocate(n);
0257     }
0258     static void deallocate(const pointer ptr, const size_type n)
0259     {  //! Deallocate n bytes from ptr
0260        //! \param ptr location to deallocate from.
0261        //! \param n number of bytes to deallocate.
0262 #ifdef BOOST_POOL_INSTRUMENT
0263        debug_info<true>::allocated -= n * sizeof(T);
0264        std::cout << "Deallocating " << n << " * " << sizeof(T) << " bytes...\n"
0265           "Total allocated is now " << debug_info<true>::allocated << std::endl;
0266 #endif
0267 #ifdef BOOST_NO_PROPER_STL_DEALLOCATE
0268       if (ptr == 0 || n == 0)
0269         return;
0270 #endif
0271       singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
0272           NextSize, MaxSize>::ordered_free(ptr, n);
0273     }
0274 };
0275 
0276 /*! \brief Specialization of pool_allocator<void>.
0277 
0278 Specialization of pool_allocator for type void: required by the standard to make this a conforming allocator type.
0279 */
0280 template<
0281     typename UserAllocator,
0282     typename Mutex,
0283     unsigned NextSize,
0284     unsigned MaxSize>
0285 class pool_allocator<void, UserAllocator, Mutex, NextSize, MaxSize>
0286 {
0287 public:
0288     typedef void*       pointer;
0289     typedef const void* const_pointer;
0290     typedef void        value_type;
0291     //! \brief Nested class rebind allows for transformation from
0292     //! pool_allocator<T> to pool_allocator<U>.
0293     //!
0294     //! Nested class rebind allows for transformation from
0295     //! pool_allocator<T> to pool_allocator<U> via the member
0296     //! typedef other.
0297     template <class U> 
0298     struct rebind
0299     {
0300        typedef pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
0301     };
0302 };
0303 
0304 //! Simple tag type used by fast_pool_allocator as a template parameter to the underlying singleton_pool.
0305 struct fast_pool_allocator_tag
0306 {
0307 };
0308 
0309  /*! \brief A C++ Standard Library conforming allocator geared towards allocating single chunks.
0310 
0311   While class template <tt>pool_allocator</tt> is a more general-purpose solution geared towards
0312   efficiently servicing requests for any number of contiguous chunks,
0313   <tt>fast_pool_allocator</tt> is also a general-purpose solution,
0314   but is geared towards efficiently servicing requests for one chunk at a time;
0315   it will work for contiguous chunks, but not as well as <tt>pool_allocator</tt>.
0316 
0317   If you are seriously concerned about performance,
0318   use <tt>fast_pool_allocator</tt> when dealing with containers such as <tt>std::list</tt>,
0319   and use <tt>pool_allocator</tt> when dealing with containers such as <tt>std::vector</tt>.
0320 
0321   The template parameters are defined as follows:
0322 
0323   <b>T</b> Type of object to allocate/deallocate.
0324 
0325   <b>UserAllocator</b>. Defines the method that the underlying Pool will use to allocate memory from the system. 
0326   See <a href="boost_pool/pool/pooling.html#boost_pool.pool.pooling.user_allocator">User Allocators</a> for details.
0327 
0328   <b>Mutex</b> Allows the user to determine the type of synchronization to be used on the underlying <tt>singleton_pool</tt>.
0329 
0330   <b>NextSize</b> The value of this parameter is passed to the underlying Pool when it is created.
0331 
0332   <b>MaxSize</b> Limit on the maximum size used.
0333 
0334    \attention
0335   The underlying singleton_pool used by the this allocator
0336   constructs a pool instance that
0337   <b>is never freed</b>.  This means that memory allocated
0338   by the allocator can be still used after main() has
0339   completed, but may mean that some memory checking programs
0340   will complain about leaks.
0341  
0342  */
0343 
0344 template <typename T,
0345     typename UserAllocator,
0346     typename Mutex,
0347     unsigned NextSize,
0348     unsigned MaxSize >
0349 class fast_pool_allocator
0350 {
0351   public:
0352     typedef T value_type;
0353     typedef UserAllocator user_allocator;
0354     typedef Mutex mutex;
0355     BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize);
0356 
0357     typedef value_type * pointer;
0358     typedef const value_type * const_pointer;
0359     typedef value_type & reference;
0360     typedef const value_type & const_reference;
0361     typedef typename pool<UserAllocator>::size_type size_type;
0362     typedef typename pool<UserAllocator>::difference_type difference_type;
0363 
0364     //! \brief Nested class rebind allows for transformation from
0365     //! fast_pool_allocator<T> to fast_pool_allocator<U>.
0366     //!
0367     //! Nested class rebind allows for transformation from
0368     //! fast_pool_allocator<T> to fast_pool_allocator<U> via the member
0369     //! typedef other.
0370     template <typename U>
0371     struct rebind
0372     {
0373       typedef fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
0374     };
0375 
0376   public:
0377     fast_pool_allocator()
0378     {
0379       //! Ensures construction of the underlying singleton_pool IFF an
0380       //! instance of this allocator is constructed during global
0381       //! initialization. See ticket #2359 for a complete explanation
0382       //! at http://svn.boost.org/trac/boost/ticket/2359 .
0383       singleton_pool<fast_pool_allocator_tag, sizeof(T),
0384                      UserAllocator, Mutex, NextSize, MaxSize>::is_from(0);
0385     }
0386 
0387     // Default copy constructor used.
0388 
0389     // Default assignment operator used.
0390 
0391     // Not explicit, mimicking std::allocator [20.4.1]
0392     template <typename U>
0393     fast_pool_allocator(
0394         const fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> &)
0395     {
0396       //! Ensures construction of the underlying singleton_pool IFF an
0397       //! instance of this allocator is constructed during global
0398       //! initialization. See ticket #2359 for a complete explanation
0399       //! at http://svn.boost.org/trac/boost/ticket/2359 .
0400       singleton_pool<fast_pool_allocator_tag, sizeof(T),
0401                      UserAllocator, Mutex, NextSize, MaxSize>::is_from(0);
0402     }
0403 
0404     // Default destructor used.
0405 
0406     static pointer address(reference r)
0407     {
0408       return &r;
0409     }
0410     static const_pointer address(const_reference s)
0411     { return &s; }
0412     static size_type max_size()
0413     { return (std::numeric_limits<size_type>::max)(); }
0414 
0415 #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
0416     template <typename U, typename... Args>
0417     void construct(U* ptr, Args&&... args)
0418     { new (ptr) U(std::forward<Args>(args)...); }
0419 #else
0420     void construct(const pointer ptr, const value_type & t)
0421     { new (ptr) T(t); }
0422 #endif
0423 
0424     void destroy(const pointer ptr)
0425     { //! Destroy ptr using destructor.
0426       ptr->~T();
0427       (void) ptr; // Avoid unused variable warning.
0428     }
0429 
0430     bool operator==(const fast_pool_allocator &) const
0431     { return true; }
0432     bool operator!=(const fast_pool_allocator &) const
0433     { return false; }
0434 
0435     static pointer allocate(const size_type n)
0436     {
0437       const pointer ret = (n == 1) ?
0438           static_cast<pointer>(
0439               (singleton_pool<fast_pool_allocator_tag, sizeof(T),
0440                   UserAllocator, Mutex, NextSize, MaxSize>::malloc)() ) :
0441           static_cast<pointer>(
0442               singleton_pool<fast_pool_allocator_tag, sizeof(T),
0443                   UserAllocator, Mutex, NextSize, MaxSize>::ordered_malloc(n) );
0444       if (ret == 0)
0445         boost::throw_exception(std::bad_alloc());
0446       return ret;
0447     }
0448     static pointer allocate(const size_type n, const void * const)
0449     { //! Allocate memory .
0450       return allocate(n);
0451     }
0452     static pointer allocate()
0453     { //! Allocate memory.
0454       const pointer ret = static_cast<pointer>(
0455           (singleton_pool<fast_pool_allocator_tag, sizeof(T),
0456               UserAllocator, Mutex, NextSize, MaxSize>::malloc)() );
0457       if (ret == 0)
0458         boost::throw_exception(std::bad_alloc());
0459       return ret;
0460     }
0461     static void deallocate(const pointer ptr, const size_type n)
0462     { //! Deallocate memory.
0463 
0464 #ifdef BOOST_NO_PROPER_STL_DEALLOCATE
0465       if (ptr == 0 || n == 0)
0466         return;
0467 #endif
0468       if (n == 1)
0469         (singleton_pool<fast_pool_allocator_tag, sizeof(T),
0470             UserAllocator, Mutex, NextSize, MaxSize>::free)(ptr);
0471       else
0472         (singleton_pool<fast_pool_allocator_tag, sizeof(T),
0473             UserAllocator, Mutex, NextSize, MaxSize>::free)(ptr, n);
0474     }
0475     static void deallocate(const pointer ptr)
0476     { //! deallocate/free
0477       (singleton_pool<fast_pool_allocator_tag, sizeof(T),
0478           UserAllocator, Mutex, NextSize, MaxSize>::free)(ptr);
0479     }
0480 };
0481 
0482 /*!  \brief Specialization of fast_pool_allocator<void>.
0483 
0484 Specialization of fast_pool_allocator<void> required to make the allocator standard-conforming.
0485 */
0486 template<
0487     typename UserAllocator,
0488     typename Mutex,
0489     unsigned NextSize,
0490     unsigned MaxSize >
0491 class fast_pool_allocator<void, UserAllocator, Mutex, NextSize, MaxSize>
0492 {
0493 public:
0494     typedef void*       pointer;
0495     typedef const void* const_pointer;
0496     typedef void        value_type;
0497 
0498     //! \brief Nested class rebind allows for transformation from
0499     //! fast_pool_allocator<T> to fast_pool_allocator<U>.
0500     //!
0501     //! Nested class rebind allows for transformation from
0502     //! fast_pool_allocator<T> to fast_pool_allocator<U> via the member
0503     //! typedef other.
0504     template <class U> struct rebind
0505     {
0506         typedef fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
0507     };
0508 };
0509 
0510 } // namespace boost
0511 
0512 #endif