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 //
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_SINGLETON_POOL_HPP
0010 #define BOOST_SINGLETON_POOL_HPP
0011 
0012 /*!
0013   \file
0014   \brief The <tt>singleton_pool</tt> class allows other pool interfaces
0015   for types of the same size to share the same underlying pool.
0016 
0017   \details Header singleton_pool.hpp provides a template class <tt>singleton_pool</tt>,
0018   which provides access to a pool as a singleton object.
0019   
0020 */
0021 
0022 #include <boost/pool/poolfwd.hpp>
0023 
0024 // boost::pool
0025 #include <boost/pool/pool.hpp>
0026 // boost::details::pool::guard
0027 #include <boost/pool/detail/guard.hpp>
0028 
0029 #include <boost/type_traits/aligned_storage.hpp>
0030 
0031 namespace boost {
0032 
0033  /*! 
0034  The singleton_pool class allows other pool interfaces
0035  for types of the same size to share the same pool.  Template
0036  parameters are as follows:
0037 
0038  <b>Tag</b> User-specified type to uniquely identify this pool: allows different unbounded sets of singleton pools to exist.
0039 
0040  <b>RequestedSize</b> The size of each chunk returned by member function <tt>malloc()</tt>.
0041 
0042  <B>UserAllocator</b> User allocator, default = default_user_allocator_new_delete.
0043 
0044  <b>Mutex</B> This class is the type of mutex to use to protect simultaneous access to the underlying Pool. 
0045  Can be any Boost.Thread Mutex type or <tt>boost::details::pool::null_mutex</tt>.
0046  It is exposed so that users may declare some singleton pools normally (i.e., with synchronization), but 
0047  some singleton pools without synchronization (by specifying <tt>boost::details::pool::null_mutex</tt>) for efficiency reasons.
0048  The member typedef <tt>mutex</tt> exposes the value of this template parameter.  The default for this
0049  parameter is boost::details::pool::default_mutex which is a synonym for either <tt>boost::details::pool::null_mutex</tt>
0050  (when threading support is turned off in the compiler (so BOOST_HAS_THREADS is not set), or threading support
0051  has ben explicitly disabled with BOOST_DISABLE_THREADS (Boost-wide disabling of threads) or BOOST_POOL_NO_MT (this library only))
0052  or for <tt>boost::mutex</tt> (when threading support is enabled in the compiler).
0053 
0054  <B>NextSize</b> The value of this parameter is passed to the underlying Pool when it is created and
0055  specifies the number of chunks to allocate in the first allocation request (defaults to 32).
0056  The member typedef <tt>static const value next_size</tt> exposes the value of this template parameter.
0057 
0058  <b>MaxSize</B>The value of this parameter is passed to the underlying Pool when it is created and
0059  specifies the maximum number of chunks to allocate in any single allocation request (defaults to 0).
0060 
0061   <b>Notes:</b>
0062 
0063   The underlying pool <i>p</i> referenced by the static functions
0064   in singleton_pool is actually declared in a way that is:
0065 
0066   1 Thread-safe if there is only one thread running before main() begins and after main() ends
0067   -- all of the static functions of singleton_pool synchronize their access to p.
0068 
0069   2 Guaranteed to be constructed before it is used --
0070   thus, the simple static object in the synopsis above would actually be an incorrect implementation.
0071   The actual implementation to guarantee this is considerably more complicated.
0072 
0073   3 Note too that a different underlying pool p exists
0074   for each different set of template parameters,
0075   including implementation-specific ones.
0076 
0077   4 The underlying pool is constructed "as if" by:
0078 
0079   pool<UserAllocator> p(RequestedSize, NextSize, MaxSize);
0080 
0081   \attention
0082   The underlying pool constructed by the singleton 
0083   <b>is never freed</b>.  This means that memory allocated
0084   by a singleton_pool can be still used after main() has
0085   completed, but may mean that some memory checking programs
0086   will complain about leaks from singleton_pool.
0087  
0088   */
0089 
0090  template <typename Tag,
0091     unsigned RequestedSize,
0092     typename UserAllocator,
0093     typename Mutex,
0094     unsigned NextSize,
0095     unsigned MaxSize >
0096 class singleton_pool
0097 {
0098   public:
0099     typedef Tag tag; /*!< The Tag template parameter uniquely
0100                      identifies this pool and allows
0101       different unbounded sets of singleton pools to exist.
0102       For example, the pool allocators use two tag classes to ensure that the
0103       two different allocator types never share the same underlying singleton pool.
0104       Tag is never actually used by singleton_pool.
0105     */
0106     typedef Mutex mutex; //!< The type of mutex used to synchonise access to this pool (default <tt>details::pool::default_mutex</tt>).
0107     typedef UserAllocator user_allocator; //!< The user-allocator used by this pool, default = <tt>default_user_allocator_new_delete</tt>.
0108     typedef typename pool<UserAllocator>::size_type size_type; //!< size_type of user allocator.
0109     typedef typename pool<UserAllocator>::difference_type difference_type; //!< difference_type of user allocator.
0110 
0111     BOOST_STATIC_CONSTANT(unsigned, requested_size = RequestedSize); //!< The size of each chunk allocated by this pool.
0112     BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize); //!< The number of chunks to allocate on the first allocation.
0113 
0114 private:
0115     singleton_pool();
0116 
0117 #ifndef BOOST_DOXYGEN
0118     struct pool_type: public Mutex, public pool<UserAllocator>
0119     {
0120       pool_type() : pool<UserAllocator>(RequestedSize, NextSize, MaxSize) {}
0121     }; //  struct pool_type: Mutex
0122 
0123 #else
0124     //
0125     // This is invoked when we build with Doxygen only:
0126     //
0127 public:
0128     static pool<UserAllocator> p; //!< For exposition only!
0129 #endif
0130 
0131 
0132   public:
0133     static void * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
0134     { //! Equivalent to SingletonPool::p.malloc(); synchronized.
0135       pool_type & p = get_pool();
0136       details::pool::guard<Mutex> g(p);
0137       return (p.malloc)();
0138     }
0139     static void * ordered_malloc()
0140     {  //! Equivalent to SingletonPool::p.ordered_malloc(); synchronized.
0141       pool_type & p = get_pool();
0142       details::pool::guard<Mutex> g(p);
0143       return p.ordered_malloc();
0144     }
0145     static void * ordered_malloc(const size_type n)
0146     { //! Equivalent to SingletonPool::p.ordered_malloc(n); synchronized.
0147       pool_type & p = get_pool();
0148       details::pool::guard<Mutex> g(p);
0149       return p.ordered_malloc(n);
0150     }
0151     static bool is_from(void * const ptr)
0152     { //! Equivalent to SingletonPool::p.is_from(chunk); synchronized.
0153       //! \returns true if chunk is from SingletonPool::is_from(chunk)
0154       pool_type & p = get_pool();
0155       details::pool::guard<Mutex> g(p);
0156       return p.is_from(ptr);
0157     }
0158     static void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const ptr)
0159     { //! Equivalent to SingletonPool::p.free(chunk); synchronized.
0160       pool_type & p = get_pool();
0161       details::pool::guard<Mutex> g(p);
0162       (p.free)(ptr);
0163     }
0164     static void ordered_free(void * const ptr)
0165     { //! Equivalent to SingletonPool::p.ordered_free(chunk); synchronized.
0166       pool_type & p = get_pool();
0167       details::pool::guard<Mutex> g(p);
0168       p.ordered_free(ptr);
0169     }
0170     static void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const ptr, const size_type n)
0171     { //! Equivalent to SingletonPool::p.free(chunk, n); synchronized.
0172       pool_type & p = get_pool();
0173       details::pool::guard<Mutex> g(p);
0174       (p.free)(ptr, n);
0175     }
0176     static void ordered_free(void * const ptr, const size_type n)
0177     { //! Equivalent to SingletonPool::p.ordered_free(chunk, n); synchronized.
0178       pool_type & p = get_pool();
0179       details::pool::guard<Mutex> g(p);
0180       p.ordered_free(ptr, n);
0181     }
0182     static bool release_memory()
0183     { //! Equivalent to SingletonPool::p.release_memory(); synchronized.
0184       pool_type & p = get_pool();
0185       details::pool::guard<Mutex> g(p);
0186       return p.release_memory();
0187     }
0188     static bool purge_memory()
0189     { //! Equivalent to SingletonPool::p.purge_memory(); synchronized.
0190       pool_type & p = get_pool();
0191       details::pool::guard<Mutex> g(p);
0192       return p.purge_memory();
0193     }
0194 
0195 private:
0196    typedef boost::aligned_storage<sizeof(pool_type), boost::alignment_of<pool_type>::value> storage_type;
0197    static storage_type storage;
0198 
0199    static pool_type& get_pool()
0200    {
0201       static bool f = false;
0202       if(!f)
0203       {
0204          // This code *must* be called before main() starts, 
0205          // and when only one thread is executing.
0206          f = true;
0207          new (&storage) pool_type;
0208       }
0209 
0210       // The following line does nothing else than force the instantiation
0211       //  of singleton<T>::create_object, whose constructor is
0212       //  called before main() begins.
0213       create_object.do_nothing();
0214 
0215       return *static_cast<pool_type*>(static_cast<void*>(&storage));
0216    }
0217 
0218    struct object_creator
0219    {
0220       object_creator()
0221       {  // This constructor does nothing more than ensure that instance()
0222          //  is called before main() begins, thus creating the static
0223          //  T object before multithreading race issues can come up.
0224          singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::get_pool();
0225       }
0226       inline void do_nothing() const
0227       {
0228       }
0229    };
0230    static object_creator create_object;
0231 }; // struct singleton_pool
0232 
0233 template <typename Tag,
0234     unsigned RequestedSize,
0235     typename UserAllocator,
0236     typename Mutex,
0237     unsigned NextSize,
0238     unsigned MaxSize >
0239 typename singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::storage_type singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::storage;
0240 
0241 template <typename Tag,
0242     unsigned RequestedSize,
0243     typename UserAllocator,
0244     typename Mutex,
0245     unsigned NextSize,
0246     unsigned MaxSize >
0247 typename singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::object_creator singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::create_object;
0248 
0249 } // namespace boost
0250 
0251 #endif