annotate DEPENDENCIES/generic/include/boost/pool/singleton_pool.hpp @ 133:4acb5d8d80b6 tip

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