LCOV - code coverage report
Current view: top level - usr/include/boost/pool - singleton_pool.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 8 24 33.3 %
Date: 2022-12-08 13:48:47 Functions: 1 7 14.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (C) 2000, 2001 Stephen Cleary
       2             : //
       3             : // Distributed under the Boost Software License, Version 1.0. (See
       4             : // accompanying file LICENSE_1_0.txt or copy at
       5             : // http://www.boost.org/LICENSE_1_0.txt)
       6             : //
       7             : // See http://www.boost.org for updates, documentation, and revision history.
       8             : 
       9             : #ifndef BOOST_SINGLETON_POOL_HPP
      10             : #define BOOST_SINGLETON_POOL_HPP
      11             : 
      12             : /*!
      13             :   \file
      14             :   \brief The <tt>singleton_pool</tt> class allows other pool interfaces
      15             :   for types of the same size to share the same underlying pool.
      16             : 
      17             :   \details Header singleton_pool.hpp provides a template class <tt>singleton_pool</tt>,
      18             :   which provides access to a pool as a singleton object.
      19             :   
      20             : */
      21             : 
      22             : #include <boost/pool/poolfwd.hpp>
      23             : 
      24             : // boost::pool
      25             : #include <boost/pool/pool.hpp>
      26             : // boost::details::pool::guard
      27             : #include <boost/pool/detail/guard.hpp>
      28             : 
      29             : #include <boost/type_traits/aligned_storage.hpp>
      30             : 
      31             : namespace boost {
      32             : 
      33             :  /*! 
      34             :  The singleton_pool class allows other pool interfaces
      35             :  for types of the same size to share the same pool.  Template
      36             :  parameters are as follows:
      37             : 
      38             :  <b>Tag</b> User-specified type to uniquely identify this pool: allows different unbounded sets of singleton pools to exist.
      39             : 
      40             :  <b>RequestedSize</b> The size of each chunk returned by member function <tt>malloc()</tt>.
      41             : 
      42             :  <B>UserAllocator</b> User allocator, default = default_user_allocator_new_delete.
      43             : 
      44             :  <b>Mutex</B> This class is the type of mutex to use to protect simultaneous access to the underlying Pool. 
      45             :  Can be any Boost.Thread Mutex type or <tt>boost::details::pool::null_mutex</tt>.
      46             :  It is exposed so that users may declare some singleton pools normally (i.e., with synchronization), but 
      47             :  some singleton pools without synchronization (by specifying <tt>boost::details::pool::null_mutex</tt>) for efficiency reasons.
      48             :  The member typedef <tt>mutex</tt> exposes the value of this template parameter.  The default for this
      49             :  parameter is boost::details::pool::default_mutex which is a synonym for either <tt>boost::details::pool::null_mutex</tt>
      50             :  (when threading support is turned off in the compiler (so BOOST_HAS_THREADS is not set), or threading support
      51             :  has ben explicitly disabled with BOOST_DISABLE_THREADS (Boost-wide disabling of threads) or BOOST_POOL_NO_MT (this library only))
      52             :  or for <tt>boost::mutex</tt> (when threading support is enabled in the compiler).
      53             : 
      54             :  <B>NextSize</b> The value of this parameter is passed to the underlying Pool when it is created and
      55             :  specifies the number of chunks to allocate in the first allocation request (defaults to 32).
      56             :  The member typedef <tt>static const value next_size</tt> exposes the value of this template parameter.
      57             : 
      58             :  <b>MaxSize</B>The value of this parameter is passed to the underlying Pool when it is created and
      59             :  specifies the maximum number of chunks to allocate in any single allocation request (defaults to 0).
      60             : 
      61             :   <b>Notes:</b>
      62             : 
      63             :   The underlying pool <i>p</i> referenced by the static functions
      64             :   in singleton_pool is actually declared in a way that is:
      65             : 
      66             :   1 Thread-safe if there is only one thread running before main() begins and after main() ends
      67             :   -- all of the static functions of singleton_pool synchronize their access to p.
      68             : 
      69             :   2 Guaranteed to be constructed before it is used --
      70             :   thus, the simple static object in the synopsis above would actually be an incorrect implementation.
      71             :   The actual implementation to guarantee this is considerably more complicated.
      72             : 
      73             :   3 Note too that a different underlying pool p exists
      74             :   for each different set of template parameters,
      75             :   including implementation-specific ones.
      76             : 
      77             :   4 The underlying pool is constructed "as if" by:
      78             : 
      79             :   pool<UserAllocator> p(RequestedSize, NextSize, MaxSize);
      80             : 
      81             :   \attention
      82             :   The underlying pool constructed by the singleton 
      83             :   <b>is never freed</b>.  This means that memory allocated
      84             :   by a singleton_pool can be still used after main() has
      85             :   completed, but may mean that some memory checking programs
      86             :   will complain about leaks from singleton_pool.
      87             :  
      88             :   */
      89             : 
      90             :  template <typename Tag,
      91             :     unsigned RequestedSize,
      92             :     typename UserAllocator,
      93             :     typename Mutex,
      94             :     unsigned NextSize,
      95             :     unsigned MaxSize >
      96             : class singleton_pool
      97             : {
      98             :   public:
      99             :     typedef Tag tag; /*!< The Tag template parameter uniquely
     100             :                      identifies this pool and allows
     101             :       different unbounded sets of singleton pools to exist.
     102             :       For example, the pool allocators use two tag classes to ensure that the
     103             :       two different allocator types never share the same underlying singleton pool.
     104             :       Tag is never actually used by singleton_pool.
     105             :     */
     106             :     typedef Mutex mutex; //!< The type of mutex used to synchonise access to this pool (default <tt>details::pool::default_mutex</tt>).
     107             :     typedef UserAllocator user_allocator; //!< The user-allocator used by this pool, default = <tt>default_user_allocator_new_delete</tt>.
     108             :     typedef typename pool<UserAllocator>::size_type size_type; //!< size_type of user allocator.
     109             :     typedef typename pool<UserAllocator>::difference_type difference_type; //!< difference_type of user allocator.
     110             : 
     111             :     BOOST_STATIC_CONSTANT(unsigned, requested_size = RequestedSize); //!< The size of each chunk allocated by this pool.
     112             :     BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize); //!< The number of chunks to allocate on the first allocation.
     113             : 
     114             : private:
     115             :     singleton_pool();
     116             : 
     117             : #ifndef BOOST_DOXYGEN
     118             :     struct pool_type: public Mutex, public pool<UserAllocator>
     119             :     {
     120           0 :       pool_type() : pool<UserAllocator>(RequestedSize, NextSize, MaxSize) {}
     121             :     }; //  struct pool_type: Mutex
     122             : 
     123             : #else
     124             :     //
     125             :     // This is invoked when we build with Doxygen only:
     126             :     //
     127             : public:
     128             :     static pool<UserAllocator> p; //!< For exposition only!
     129             : #endif
     130             : 
     131             : 
     132             :   public:
     133           0 :     static void * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
     134             :     { //! Equivalent to SingletonPool::p.malloc(); synchronized.
     135           0 :       pool_type & p = get_pool();
     136           0 :       details::pool::guard<Mutex> g(p);
     137           0 :       return (p.malloc)();
     138             :     }
     139             :     static void * ordered_malloc()
     140             :     {  //! Equivalent to SingletonPool::p.ordered_malloc(); synchronized.
     141             :       pool_type & p = get_pool();
     142             :       details::pool::guard<Mutex> g(p);
     143             :       return p.ordered_malloc();
     144             :     }
     145           0 :     static void * ordered_malloc(const size_type n)
     146             :     { //! Equivalent to SingletonPool::p.ordered_malloc(n); synchronized.
     147           0 :       pool_type & p = get_pool();
     148           0 :       details::pool::guard<Mutex> g(p);
     149           0 :       return p.ordered_malloc(n);
     150             :     }
     151         712 :     static bool is_from(void * const ptr)
     152             :     { //! Equivalent to SingletonPool::p.is_from(chunk); synchronized.
     153             :       //! \returns true if chunk is from SingletonPool::is_from(chunk)
     154         712 :       pool_type & p = get_pool();
     155        2136 :       details::pool::guard<Mutex> g(p);
     156        1424 :       return p.is_from(ptr);
     157             :     }
     158           0 :     static void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const ptr)
     159             :     { //! Equivalent to SingletonPool::p.free(chunk); synchronized.
     160           0 :       pool_type & p = get_pool();
     161           0 :       details::pool::guard<Mutex> g(p);
     162           0 :       (p.free)(ptr);
     163           0 :     }
     164             :     static void ordered_free(void * const ptr)
     165             :     { //! Equivalent to SingletonPool::p.ordered_free(chunk); synchronized.
     166             :       pool_type & p = get_pool();
     167             :       details::pool::guard<Mutex> g(p);
     168             :       p.ordered_free(ptr);
     169             :     }
     170             :     static void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const ptr, const size_type n)
     171             :     { //! Equivalent to SingletonPool::p.free(chunk, n); synchronized.
     172             :       pool_type & p = get_pool();
     173             :       details::pool::guard<Mutex> g(p);
     174             :       (p.free)(ptr, n);
     175             :     }
     176             :     static void ordered_free(void * const ptr, const size_type n)
     177             :     { //! Equivalent to SingletonPool::p.ordered_free(chunk, n); synchronized.
     178             :       pool_type & p = get_pool();
     179             :       details::pool::guard<Mutex> g(p);
     180             :       p.ordered_free(ptr, n);
     181             :     }
     182             :     static bool release_memory()
     183             :     { //! Equivalent to SingletonPool::p.release_memory(); synchronized.
     184             :       pool_type & p = get_pool();
     185             :       details::pool::guard<Mutex> g(p);
     186             :       return p.release_memory();
     187             :     }
     188             :     static bool purge_memory()
     189             :     { //! Equivalent to SingletonPool::p.purge_memory(); synchronized.
     190             :       pool_type & p = get_pool();
     191             :       details::pool::guard<Mutex> g(p);
     192             :       return p.purge_memory();
     193             :     }
     194             : 
     195             : private:
     196             :    typedef boost::aligned_storage<sizeof(pool_type), boost::alignment_of<pool_type>::value> storage_type;
     197             :    static storage_type storage;
     198             : 
     199         712 :    static pool_type& get_pool()
     200             :    {
     201             :       static bool f = false;
     202         712 :       if(!f)
     203             :       {
     204             :          // This code *must* be called before main() starts, 
     205             :          // and when only one thread is executing.
     206           0 :          f = true;
     207           0 :          new (&storage) pool_type;
     208             :       }
     209             : 
     210             :       // The following line does nothing else than force the instantiation
     211             :       //  of singleton<T>::create_object, whose constructor is
     212             :       //  called before main() begins.
     213         712 :       create_object.do_nothing();
     214             : 
     215             :       return *static_cast<pool_type*>(static_cast<void*>(&storage));
     216             :    }
     217             : 
     218             :    struct object_creator
     219             :    {
     220             :       object_creator()
     221             :       {  // This constructor does nothing more than ensure that instance()
     222             :          //  is called before main() begins, thus creating the static
     223             :          //  T object before multithreading race issues can come up.
     224             :          singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::get_pool();
     225             :       }
     226         712 :       inline void do_nothing() const
     227             :       {
     228             :       }
     229             :    };
     230             :    static object_creator create_object;
     231             : }; // struct singleton_pool
     232             : 
     233             : template <typename Tag,
     234             :     unsigned RequestedSize,
     235             :     typename UserAllocator,
     236             :     typename Mutex,
     237             :     unsigned NextSize,
     238             :     unsigned MaxSize >
     239             : typename singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::storage_type singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::storage;
     240             : 
     241             : template <typename Tag,
     242             :     unsigned RequestedSize,
     243             :     typename UserAllocator,
     244             :     typename Mutex,
     245             :     unsigned NextSize,
     246             :     unsigned MaxSize >
     247             : typename singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::object_creator singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::create_object;
     248             : 
     249             : } // namespace boost
     250             : 
     251             : #endif

Generated by: LCOV version 1.14