]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/pool/object_pool.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / pool / object_pool.hpp
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_OBJECT_POOL_HPP
10 #define BOOST_OBJECT_POOL_HPP
11 /*!
12 \file
13 \brief Provides a template type boost::object_pool<T, UserAllocator>
14 that can be used for fast and efficient memory allocation of objects of type T.
15 It also provides automatic destruction of non-deallocated objects.
16 */
17
18 #include <boost/pool/poolfwd.hpp>
19
20 // boost::pool
21 #include <boost/pool/pool.hpp>
22
23 // The following code will be put into Boost.Config in a later revision
24 #if defined(BOOST_MSVC) || defined(__KCC)
25 # define BOOST_NO_TEMPLATE_CV_REF_OVERLOADS
26 #endif
27
28 // The following code might be put into some Boost.Config header in a later revision
29 #ifdef __BORLANDC__
30 # pragma option push -w-inl
31 #endif
32
33 // There are a few places in this file where the expression "this->m" is used.
34 // This expression is used to force instantiation-time name lookup, which I am
35 // informed is required for strict Standard compliance. It's only necessary
36 // if "m" is a member of a base class that is dependent on a template
37 // parameter.
38 // Thanks to Jens Maurer for pointing this out!
39
40 namespace boost {
41
42 /*! \brief A template class
43 that can be used for fast and efficient memory allocation of objects.
44 It also provides automatic destruction of non-deallocated objects.
45
46 \details
47
48 <b>T</b> The type of object to allocate/deallocate.
49 T must have a non-throwing destructor.
50
51 <b>UserAllocator</b>
52 Defines the allocator that the underlying Pool will use to allocate memory from the system.
53 See <a href="boost_pool/pool/pooling.html#boost_pool.pool.pooling.user_allocator">User Allocators</a> for details.
54
55 Class object_pool is a template class
56 that can be used for fast and efficient memory allocation of objects.
57 It also provides automatic destruction of non-deallocated objects.
58
59 When the object pool is destroyed, then the destructor for type T
60 is called for each allocated T that has not yet been deallocated. O(N).
61
62 Whenever an object of type ObjectPool needs memory from the system,
63 it will request it from its UserAllocator template parameter.
64 The amount requested is determined using a doubling algorithm;
65 that is, each time more system memory is allocated,
66 the amount of system memory requested is doubled.
67 Users may control the doubling algorithm by the parameters passed
68 to the object_pool's constructor.
69 */
70
71 template <typename T, typename UserAllocator>
72 class object_pool: protected pool<UserAllocator>
73 { //!
74 public:
75 typedef T element_type; //!< ElementType
76 typedef UserAllocator user_allocator; //!<
77 typedef typename pool<UserAllocator>::size_type size_type; //!< pool<UserAllocator>::size_type
78 typedef typename pool<UserAllocator>::difference_type difference_type; //!< pool<UserAllocator>::difference_type
79
80 protected:
81 //! \return The underlying boost:: \ref pool storage used by *this.
82 pool<UserAllocator> & store()
83 {
84 return *this;
85 }
86 //! \return The underlying boost:: \ref pool storage used by *this.
87 const pool<UserAllocator> & store() const
88 {
89 return *this;
90 }
91
92 // for the sake of code readability :)
93 static void * & nextof(void * const ptr)
94 { //! \returns The next memory block after ptr (for the sake of code readability :)
95 return *(static_cast<void **>(ptr));
96 }
97
98 public:
99 explicit object_pool(const size_type arg_next_size = 32, const size_type arg_max_size = 0)
100 :
101 pool<UserAllocator>(sizeof(T), arg_next_size, arg_max_size)
102 { //! Constructs a new (empty by default) ObjectPool.
103 //! \param next_size Number of chunks to request from the system the next time that object needs to allocate system memory (default 32).
104 //! \pre next_size != 0.
105 //! \param max_size Maximum number of chunks to ever request from the system - this puts a cap on the doubling algorithm
106 //! used by the underlying pool.
107 }
108
109 ~object_pool();
110
111 // Returns 0 if out-of-memory.
112 element_type * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
113 { //! Allocates memory that can hold one object of type ElementType.
114 //!
115 //! If out of memory, returns 0.
116 //!
117 //! Amortized O(1).
118 return static_cast<element_type *>(store().ordered_malloc());
119 }
120 void free BOOST_PREVENT_MACRO_SUBSTITUTION(element_type * const chunk)
121 { //! De-Allocates memory that holds a chunk of type ElementType.
122 //!
123 //! Note that p may not be 0.\n
124 //!
125 //! Note that the destructor for p is not called. O(N).
126 store().ordered_free(chunk);
127 }
128 bool is_from(element_type * const chunk) const
129 { /*! \returns true if chunk was allocated from *this or
130 may be returned as the result of a future allocation from *this.
131
132 Returns false if chunk was allocated from some other pool or
133 may be returned as the result of a future allocation from some other pool.
134
135 Otherwise, the return value is meaningless.
136
137 \note This function may NOT be used to reliably test random pointer values!
138 */
139 return store().is_from(chunk);
140 }
141
142 element_type * construct()
143 { //! \returns A pointer to an object of type T, allocated in memory from the underlying pool
144 //! and default constructed. The returned objected can be freed by a call to \ref destroy.
145 //! Otherwise the returned object will be automatically destroyed when *this is destroyed.
146 element_type * const ret = (malloc)();
147 if (ret == 0)
148 return ret;
149 try { new (ret) element_type(); }
150 catch (...) { (free)(ret); throw; }
151 return ret;
152 }
153
154
155 #if defined(BOOST_DOXYGEN)
156 template <class Arg1, ... class ArgN>
157 element_type * construct(Arg1&, ... ArgN&)
158 {
159 //! \returns A pointer to an object of type T, allocated in memory from the underlying pool
160 //! and constructed from arguments Arg1 to ArgN. The returned objected can be freed by a call to \ref destroy.
161 //! Otherwise the returned object will be automatically destroyed when *this is destroyed.
162 //!
163 //! \note Since the number and type of arguments to this function is totally arbitrary, a simple system has been
164 //! set up to automatically generate template construct functions. This system is based on the macro preprocessor
165 //! m4, which is standard on UNIX systems and also available for Win32 systems.\n\n
166 //! detail/pool_construct.m4, when run with m4, will create the file detail/pool_construct.ipp, which only defines
167 //! the construct functions for the proper number of arguments. The number of arguments may be passed into the
168 //! file as an m4 macro, NumberOfArguments; if not provided, it will default to 3.\n\n
169 //! For each different number of arguments (1 to NumberOfArguments), a template function is generated. There
170 //! are the same number of template parameters as there are arguments, and each argument's type is a reference
171 //! to that (possibly cv-qualified) template argument. Each possible permutation of the cv-qualifications is also generated.\n\n
172 //! Because each permutation is generated for each possible number of arguments, the included file size grows
173 //! exponentially in terms of the number of constructor arguments, not linearly. For the sake of rational
174 //! compile times, only use as many arguments as you need.\n\n
175 //! detail/pool_construct.bat and detail/pool_construct.sh are also provided to call m4, defining NumberOfArguments
176 //! to be their command-line parameter. See these files for more details.
177 }
178 #else
179 // Include automatically-generated file for family of template construct() functions.
180 // Copy .inc renamed .ipp to conform to Doxygen include filename expectations, PAB 12 Jan 11.
181 // But still get Doxygen warning:
182 // I:/boost-sandbox/guild/pool/boost/pool/object_pool.hpp:82:
183 // Warning: include file boost/pool/detail/pool_construct.ipp
184 // not found, perhaps you forgot to add its directory to INCLUDE_PATH?
185 // But the file IS found and referenced OK, but cannot view code.
186 // This seems because not at the head of the file
187 // But if moved this up, Doxygen is happy, but of course it won't compile,
188 // because the many constructors *must* go here.
189
190 #ifndef BOOST_NO_TEMPLATE_CV_REF_OVERLOADS
191 # include <boost/pool/detail/pool_construct.ipp>
192 #else
193 # include <boost/pool/detail/pool_construct_simple.ipp>
194 #endif
195 #endif
196 void destroy(element_type * const chunk)
197 { //! Destroys an object allocated with \ref construct.
198 //!
199 //! Equivalent to:
200 //!
201 //! p->~ElementType(); this->free(p);
202 //!
203 //! \pre p must have been previously allocated from *this via a call to \ref construct.
204 chunk->~T();
205 (free)(chunk);
206 }
207
208 size_type get_next_size() const
209 { //! \returns The number of chunks that will be allocated next time we run out of memory.
210 return store().get_next_size();
211 }
212 void set_next_size(const size_type x)
213 { //! Set a new number of chunks to allocate the next time we run out of memory.
214 //! \param x wanted next_size (must not be zero).
215 store().set_next_size(x);
216 }
217 };
218
219 template <typename T, typename UserAllocator>
220 object_pool<T, UserAllocator>::~object_pool()
221 {
222 #ifndef BOOST_POOL_VALGRIND
223 // handle trivial case of invalid list.
224 if (!this->list.valid())
225 return;
226
227 details::PODptr<size_type> iter = this->list;
228 details::PODptr<size_type> next = iter;
229
230 // Start 'freed_iter' at beginning of free list
231 void * freed_iter = this->first;
232
233 const size_type partition_size = this->alloc_size();
234
235 do
236 {
237 // increment next
238 next = next.next();
239
240 // delete all contained objects that aren't freed.
241
242 // Iterate 'i' through all chunks in the memory block.
243 for (char * i = iter.begin(); i != iter.end(); i += partition_size)
244 {
245 // If this chunk is free,
246 if (i == freed_iter)
247 {
248 // Increment freed_iter to point to next in free list.
249 freed_iter = nextof(freed_iter);
250
251 // Continue searching chunks in the memory block.
252 continue;
253 }
254
255 // This chunk is not free (allocated), so call its destructor,
256 static_cast<T *>(static_cast<void *>(i))->~T();
257 // and continue searching chunks in the memory block.
258 }
259
260 // free storage.
261 (UserAllocator::free)(iter.begin());
262
263 // increment iter.
264 iter = next;
265 } while (iter.valid());
266
267 // Make the block list empty so that the inherited destructor doesn't try to
268 // free it again.
269 this->list.invalidate();
270 #else
271 // destruct all used elements:
272 for(std::set<void*>::iterator pos = this->used_list.begin(); pos != this->used_list.end(); ++pos)
273 {
274 static_cast<T*>(*pos)->~T();
275 }
276 // base class will actually free the memory...
277 #endif
278 }
279
280 } // namespace boost
281
282 // The following code might be put into some Boost.Config header in a later revision
283 #ifdef __BORLANDC__
284 # pragma option pop
285 #endif
286
287 #endif