|
||||
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
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |