1 // Copyright (C) 2000, 2001 Stephen Cleary
2 // Copyright (C) 2010 Paul A. Bristow added Doxygen comments.
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // See http://www.boost.org for updates, documentation, and revision history.
10 #ifndef BOOST_POOL_ALLOC_HPP
11 #define BOOST_POOL_ALLOC_HPP
15 \brief C++ Standard Library compatible pool-based allocators.
16 \details This header provides two template types -
17 \ref pool_allocator and \ref fast_pool_allocator -
18 that can be used for fast and efficient memory allocation
19 in conjunction with the C++ Standard Library containers.
21 These types both satisfy the Standard Allocator requirements [20.1.5]
22 and the additional requirements in [20.1.5/4],
23 so they can be used with either Standard or user-supplied containers.
25 In addition, the fast_pool_allocator also provides an additional allocation
26 and an additional deallocation function:
29 <tr><th>Expression</th><th>Return Type</th><th>Semantic Equivalence<th></tr>
30 <tr><td><tt>PoolAlloc::allocate()</tt></td><td><tt>T *</tt></td><td><tt>PoolAlloc::allocate(1)</tt></tr>
31 <tr><td><tt>PoolAlloc::deallocate(p)</tt></td><td>void</tt></td><td><tt>PoolAlloc::deallocate(p, 1)</tt></tr>
34 The typedef user_allocator publishes the value of the UserAllocator template parameter.
38 If the allocation functions run out of memory, they will throw <tt>std::bad_alloc</tt>.
40 The underlying Pool type used by the allocators is accessible through the Singleton Pool Interface.
41 The identifying tag used for pool_allocator is pool_allocator_tag,
42 and the tag used for fast_pool_allocator is fast_pool_allocator_tag.
43 All template parameters of the allocators (including implementation-specific ones)
44 determine the type of the underlying Pool,
45 with the exception of the first parameter T, whose size is used instead.
47 Since the size of T is used to determine the type of the underlying Pool,
48 each allocator for different types of the same size will share the same underlying pool.
49 The tag class prevents pools from being shared between pool_allocator and fast_pool_allocator.
50 For example, on a system where
51 <tt>sizeof(int) == sizeof(void *)</tt>, <tt>pool_allocator<int></tt> and <tt>pool_allocator<void *></tt>
52 will both allocate/deallocate from/to the same pool.
54 If there is only one thread running before main() starts and after main() ends,
55 then both allocators are completely thread-safe.
57 <b>Compiler and STL Notes</b>
59 A number of common STL libraries contain bugs in their using of allocators.
60 Specifically, they pass null pointers to the deallocate function,
61 which is explicitly forbidden by the Standard [20.1.5 Table 32].
62 PoolAlloc will work around these libraries if it detects them;
63 currently, workarounds are in place for:
64 Borland C++ (Builder and command-line compiler)
65 with default (RogueWave) library, ver. 5 and earlier,
66 STLport (with any compiler), ver. 4.0 and earlier.
69 // std::numeric_limits
70 #include <boost/limits.hpp>
71 // new, std::bad_alloc
74 #include <boost/throw_exception.hpp>
75 #include <boost/pool/poolfwd.hpp>
77 // boost::singleton_pool
78 #include <boost/pool/singleton_pool.hpp>
80 #include <boost/detail/workaround.hpp>
82 // C++11 features detection
83 #include <boost/config.hpp>
86 #ifdef BOOST_HAS_VARIADIC_TMPL
90 #ifdef BOOST_POOL_INSTRUMENT
95 // The following code will be put into Boost.Config in a later revision
96 #if defined(_RWSTD_VER) || defined(__SGI_STL_PORT) || \
97 BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
98 #define BOOST_NO_PROPER_STL_DEALLOCATE
103 #ifdef BOOST_POOL_INSTRUMENT
108 static unsigned allocated;
112 unsigned debug_info<b>::allocated = 0;
116 //! Simple tag type used by pool_allocator as an argument to the
117 //! underlying singleton_pool.
118 struct pool_allocator_tag
122 /*! \brief A C++ Standard Library conforming allocator, based on an underlying pool.
124 Template parameters for pool_allocator are defined as follows:
126 <b>T</b> Type of object to allocate/deallocate.
128 <b>UserAllocator</B>. Defines the method that the underlying Pool will use to allocate memory from the system. See
129 <a href="boost_pool/pool/pooling.html#boost_pool.pool.pooling.user_allocator">User Allocators</a> for details.
131 <b>Mutex</b> Allows the user to determine the type of synchronization to be used on the underlying singleton_pool.
133 <b>NextSize</b> The value of this parameter is passed to the underlying singleton_pool when it is created.
135 <b>MaxSize</b> Limit on the maximum size used.
138 The underlying singleton_pool used by the this allocator
139 constructs a pool instance that
140 <b>is never freed</b>. This means that memory allocated
141 by the allocator can be still used after main() has
142 completed, but may mean that some memory checking programs
143 will complain about leaks.
147 template <typename T,
148 typename UserAllocator,
155 typedef T value_type; //!< value_type of template parameter T.
156 typedef UserAllocator user_allocator; //!< allocator that defines the method that the underlying Pool will use to allocate memory from the system.
157 typedef Mutex mutex; //!< typedef mutex publishes the value of the template parameter Mutex.
158 BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize); //!< next_size publishes the values of the template parameter NextSize.
160 typedef value_type * pointer; //!<
161 typedef const value_type * const_pointer;
162 typedef value_type & reference;
163 typedef const value_type & const_reference;
164 typedef typename pool<UserAllocator>::size_type size_type;
165 typedef typename pool<UserAllocator>::difference_type difference_type;
167 //! \brief Nested class rebind allows for transformation from
168 //! pool_allocator<T> to pool_allocator<U>.
170 //! Nested class rebind allows for transformation from
171 //! pool_allocator<T> to pool_allocator<U> via the member
173 template <typename U>
176 typedef pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
181 { /*! Results in default construction of the underlying singleton_pool IFF an
182 instance of this allocator is constructed during global initialization (
183 required to ensure construction of singleton_pool IFF an
184 instance of this allocator is constructed during global
185 initialization. See ticket #2359 for a complete explanation at
186 http://svn.boost.org/trac/boost/ticket/2359) .
188 singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
189 NextSize, MaxSize>::is_from(0);
192 // default copy constructor.
194 // default assignment operator.
196 // not explicit, mimicking std::allocator [20.4.1]
197 template <typename U>
198 pool_allocator(const pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> &)
199 { /*! Results in the default construction of the underlying singleton_pool, this
200 is required to ensure construction of singleton_pool IFF an
201 instance of this allocator is constructed during global
202 initialization. See ticket #2359 for a complete explanation
203 at http://svn.boost.org/trac/boost/ticket/2359 .
205 singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
206 NextSize, MaxSize>::is_from(0);
209 // default destructor
211 static pointer address(reference r)
213 static const_pointer address(const_reference s)
215 static size_type max_size()
216 { return (std::numeric_limits<size_type>::max)(); }
218 #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
219 template <typename U, typename... Args>
220 static void construct(U* ptr, Args&&... args)
221 { new (ptr) U(std::forward<Args>(args)...); }
223 static void construct(const pointer ptr, const value_type & t)
227 static void destroy(const pointer ptr)
230 (void) ptr; // avoid unused variable warning.
233 bool operator==(const pool_allocator &) const
235 bool operator!=(const pool_allocator &) const
238 static pointer allocate(const size_type n)
240 #ifdef BOOST_POOL_INSTRUMENT
241 debug_info<true>::allocated += n * sizeof(T);
242 std::cout << "Allocating " << n << " * " << sizeof(T) << " bytes...\n"
243 "Total allocated is now " << debug_info<true>::allocated << std::endl;
245 const pointer ret = static_cast<pointer>(
246 singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
247 NextSize, MaxSize>::ordered_malloc(n) );
249 boost::throw_exception(std::bad_alloc());
252 static pointer allocate(const size_type n, const void * const)
253 { //! allocate n bytes
254 //! \param n bytes to allocate.
258 static void deallocate(const pointer ptr, const size_type n)
259 { //! Deallocate n bytes from ptr
260 //! \param ptr location to deallocate from.
261 //! \param n number of bytes to deallocate.
262 #ifdef BOOST_POOL_INSTRUMENT
263 debug_info<true>::allocated -= n * sizeof(T);
264 std::cout << "Deallocating " << n << " * " << sizeof(T) << " bytes...\n"
265 "Total allocated is now " << debug_info<true>::allocated << std::endl;
267 #ifdef BOOST_NO_PROPER_STL_DEALLOCATE
268 if (ptr == 0 || n == 0)
271 singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
272 NextSize, MaxSize>::ordered_free(ptr, n);
276 /*! \brief Specialization of pool_allocator<void>.
278 Specialization of pool_allocator for type void: required by the standard to make this a conforming allocator type.
281 typename UserAllocator,
285 class pool_allocator<void, UserAllocator, Mutex, NextSize, MaxSize>
288 typedef void* pointer;
289 typedef const void* const_pointer;
290 typedef void value_type;
291 //! \brief Nested class rebind allows for transformation from
292 //! pool_allocator<T> to pool_allocator<U>.
294 //! Nested class rebind allows for transformation from
295 //! pool_allocator<T> to pool_allocator<U> via the member
300 typedef pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
304 //! Simple tag type used by fast_pool_allocator as a template parameter to the underlying singleton_pool.
305 struct fast_pool_allocator_tag
309 /*! \brief A C++ Standard Library conforming allocator geared towards allocating single chunks.
311 While class template <tt>pool_allocator</tt> is a more general-purpose solution geared towards
312 efficiently servicing requests for any number of contiguous chunks,
313 <tt>fast_pool_allocator</tt> is also a general-purpose solution,
314 but is geared towards efficiently servicing requests for one chunk at a time;
315 it will work for contiguous chunks, but not as well as <tt>pool_allocator</tt>.
317 If you are seriously concerned about performance,
318 use <tt>fast_pool_allocator</tt> when dealing with containers such as <tt>std::list</tt>,
319 and use <tt>pool_allocator</tt> when dealing with containers such as <tt>std::vector</tt>.
321 The template parameters are defined as follows:
323 <b>T</b> Type of object to allocate/deallocate.
325 <b>UserAllocator</b>. Defines the method that the underlying Pool will use to allocate memory from the system.
326 See <a href="boost_pool/pool/pooling.html#boost_pool.pool.pooling.user_allocator">User Allocators</a> for details.
328 <b>Mutex</b> Allows the user to determine the type of synchronization to be used on the underlying <tt>singleton_pool</tt>.
330 <b>NextSize</b> The value of this parameter is passed to the underlying Pool when it is created.
332 <b>MaxSize</b> Limit on the maximum size used.
335 The underlying singleton_pool used by the this allocator
336 constructs a pool instance that
337 <b>is never freed</b>. This means that memory allocated
338 by the allocator can be still used after main() has
339 completed, but may mean that some memory checking programs
340 will complain about leaks.
344 template <typename T,
345 typename UserAllocator,
349 class fast_pool_allocator
352 typedef T value_type;
353 typedef UserAllocator user_allocator;
355 BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize);
357 typedef value_type * pointer;
358 typedef const value_type * const_pointer;
359 typedef value_type & reference;
360 typedef const value_type & const_reference;
361 typedef typename pool<UserAllocator>::size_type size_type;
362 typedef typename pool<UserAllocator>::difference_type difference_type;
364 //! \brief Nested class rebind allows for transformation from
365 //! fast_pool_allocator<T> to fast_pool_allocator<U>.
367 //! Nested class rebind allows for transformation from
368 //! fast_pool_allocator<T> to fast_pool_allocator<U> via the member
370 template <typename U>
373 typedef fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
377 fast_pool_allocator()
379 //! Ensures construction of the underlying singleton_pool IFF an
380 //! instance of this allocator is constructed during global
381 //! initialization. See ticket #2359 for a complete explanation
382 //! at http://svn.boost.org/trac/boost/ticket/2359 .
383 singleton_pool<fast_pool_allocator_tag, sizeof(T),
384 UserAllocator, Mutex, NextSize, MaxSize>::is_from(0);
387 // Default copy constructor used.
389 // Default assignment operator used.
391 // Not explicit, mimicking std::allocator [20.4.1]
392 template <typename U>
394 const fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> &)
396 //! Ensures construction of the underlying singleton_pool IFF an
397 //! instance of this allocator is constructed during global
398 //! initialization. See ticket #2359 for a complete explanation
399 //! at http://svn.boost.org/trac/boost/ticket/2359 .
400 singleton_pool<fast_pool_allocator_tag, sizeof(T),
401 UserAllocator, Mutex, NextSize, MaxSize>::is_from(0);
404 // Default destructor used.
406 static pointer address(reference r)
410 static const_pointer address(const_reference s)
412 static size_type max_size()
413 { return (std::numeric_limits<size_type>::max)(); }
415 #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
416 template <typename U, typename... Args>
417 void construct(U* ptr, Args&&... args)
418 { new (ptr) U(std::forward<Args>(args)...); }
420 void construct(const pointer ptr, const value_type & t)
424 void destroy(const pointer ptr)
425 { //! Destroy ptr using destructor.
427 (void) ptr; // Avoid unused variable warning.
430 bool operator==(const fast_pool_allocator &) const
432 bool operator!=(const fast_pool_allocator &) const
435 static pointer allocate(const size_type n)
437 const pointer ret = (n == 1) ?
438 static_cast<pointer>(
439 (singleton_pool<fast_pool_allocator_tag, sizeof(T),
440 UserAllocator, Mutex, NextSize, MaxSize>::malloc)() ) :
441 static_cast<pointer>(
442 singleton_pool<fast_pool_allocator_tag, sizeof(T),
443 UserAllocator, Mutex, NextSize, MaxSize>::ordered_malloc(n) );
445 boost::throw_exception(std::bad_alloc());
448 static pointer allocate(const size_type n, const void * const)
449 { //! Allocate memory .
452 static pointer allocate()
453 { //! Allocate memory.
454 const pointer ret = static_cast<pointer>(
455 (singleton_pool<fast_pool_allocator_tag, sizeof(T),
456 UserAllocator, Mutex, NextSize, MaxSize>::malloc)() );
458 boost::throw_exception(std::bad_alloc());
461 static void deallocate(const pointer ptr, const size_type n)
462 { //! Deallocate memory.
464 #ifdef BOOST_NO_PROPER_STL_DEALLOCATE
465 if (ptr == 0 || n == 0)
469 (singleton_pool<fast_pool_allocator_tag, sizeof(T),
470 UserAllocator, Mutex, NextSize, MaxSize>::free)(ptr);
472 (singleton_pool<fast_pool_allocator_tag, sizeof(T),
473 UserAllocator, Mutex, NextSize, MaxSize>::free)(ptr, n);
475 static void deallocate(const pointer ptr)
476 { //! deallocate/free
477 (singleton_pool<fast_pool_allocator_tag, sizeof(T),
478 UserAllocator, Mutex, NextSize, MaxSize>::free)(ptr);
482 /*! \brief Specialization of fast_pool_allocator<void>.
484 Specialization of fast_pool_allocator<void> required to make the allocator standard-conforming.
487 typename UserAllocator,
491 class fast_pool_allocator<void, UserAllocator, Mutex, NextSize, MaxSize>
494 typedef void* pointer;
495 typedef const void* const_pointer;
496 typedef void value_type;
498 //! \brief Nested class rebind allows for transformation from
499 //! fast_pool_allocator<T> to fast_pool_allocator<U>.
501 //! Nested class rebind allows for transformation from
502 //! fast_pool_allocator<T> to fast_pool_allocator<U> via the member
504 template <class U> struct rebind
506 typedef fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;