Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / pool / pool_alloc.hpp
1 // Copyright (C) 2000, 2001 Stephen Cleary
2 // Copyright (C) 2010 Paul A. Bristow added Doxygen comments.
3 //
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)
7 //
8 // See http://www.boost.org for updates, documentation, and revision history.
9
10 #ifndef BOOST_POOL_ALLOC_HPP
11 #define BOOST_POOL_ALLOC_HPP
12
13 /*!
14   \file
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.
20
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.
24
25   In addition, the fast_pool_allocator also provides an additional allocation
26   and an additional deallocation function:
27
28 <table>
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>
32 </table>
33
34 The typedef user_allocator publishes the value of the UserAllocator template parameter.
35
36 <b>Notes</b>
37
38 If the allocation functions run out of memory, they will throw <tt>std::bad_alloc</tt>.
39
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.
46
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.
53
54 If there is only one thread running before main() starts and after main() ends,
55 then both allocators are completely thread-safe.
56
57 <b>Compiler and STL Notes</b>
58
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.
67 */
68
69 // std::numeric_limits
70 #include <boost/limits.hpp>
71 // new, std::bad_alloc
72 #include <new>
73
74 #include <boost/throw_exception.hpp>
75 #include <boost/pool/poolfwd.hpp>
76
77 // boost::singleton_pool
78 #include <boost/pool/singleton_pool.hpp>
79
80 #include <boost/detail/workaround.hpp>
81
82 // C++11 features detection
83 #include <boost/config.hpp>
84
85 // std::forward
86 #ifdef BOOST_HAS_VARIADIC_TMPL
87 #include <utility>
88 #endif
89
90 #ifdef BOOST_POOL_INSTRUMENT
91 #include <iostream>
92 #include <iomanip>
93 #endif
94
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
99 #endif
100
101 namespace boost {
102
103 #ifdef BOOST_POOL_INSTRUMENT
104
105 template <bool b>
106 struct debug_info
107 {
108    static unsigned allocated;
109 };
110
111 template <bool b>
112 unsigned debug_info<b>::allocated = 0;
113
114 #endif
115
116  //! Simple tag type used by pool_allocator as an argument to the
117  //! underlying singleton_pool.
118  struct pool_allocator_tag
119 {
120 };
121
122 /*!  \brief A C++ Standard Library conforming allocator, based on an underlying pool.
123
124   Template parameters for pool_allocator are defined as follows:
125
126   <b>T</b> Type of object to allocate/deallocate.
127
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.
130
131   <b>Mutex</b> Allows the user to determine the type of synchronization to be used on the underlying singleton_pool. 
132
133   <b>NextSize</b> The value of this parameter is passed to the underlying singleton_pool when it is created.
134
135   <b>MaxSize</b> Limit on the maximum size used.
136
137   \attention
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.
144  
145   
146   */
147 template <typename T,
148     typename UserAllocator,
149     typename Mutex,
150     unsigned NextSize,
151     unsigned MaxSize >
152 class pool_allocator
153 {
154   public:
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.
159
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;
166
167     //! \brief Nested class rebind allows for transformation from
168     //! pool_allocator<T> to pool_allocator<U>.
169     //!
170     //! Nested class rebind allows for transformation from
171     //! pool_allocator<T> to pool_allocator<U> via the member
172     //! typedef other.
173     template <typename U>
174     struct rebind
175     { //
176       typedef pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
177     };
178
179   public:
180     pool_allocator()
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) .
187        */
188       singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
189                      NextSize, MaxSize>::is_from(0);
190     }
191
192     // default copy constructor.
193
194     // default assignment operator.
195
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 .
204        */
205       singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
206                      NextSize, MaxSize>::is_from(0);
207     }
208
209     // default destructor
210
211     static pointer address(reference r)
212     { return &r; }
213     static const_pointer address(const_reference s)
214     { return &s; }
215     static size_type max_size()
216     { return (std::numeric_limits<size_type>::max)(); }
217
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)...); }
222 #else
223     static void construct(const pointer ptr, const value_type & t)
224     { new (ptr) T(t); }
225 #endif
226
227     static void destroy(const pointer ptr)
228     {
229       ptr->~T();
230       (void) ptr; // avoid unused variable warning.
231     }
232
233     bool operator==(const pool_allocator &) const
234     { return true; }
235     bool operator!=(const pool_allocator &) const
236     { return false; }
237
238     static pointer allocate(const size_type n)
239     {
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;
244 #endif
245       const pointer ret = static_cast<pointer>(
246           singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
247               NextSize, MaxSize>::ordered_malloc(n) );
248       if ((ret == 0) && n)
249         boost::throw_exception(std::bad_alloc());
250       return ret;
251     }
252     static pointer allocate(const size_type n, const void * const)
253     { //! allocate n bytes
254     //! \param n bytes to allocate.
255     //! \param unused.
256       return allocate(n);
257     }
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;
266 #endif
267 #ifdef BOOST_NO_PROPER_STL_DEALLOCATE
268       if (ptr == 0 || n == 0)
269         return;
270 #endif
271       singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
272           NextSize, MaxSize>::ordered_free(ptr, n);
273     }
274 };
275
276 /*! \brief Specialization of pool_allocator<void>.
277
278 Specialization of pool_allocator for type void: required by the standard to make this a conforming allocator type.
279 */
280 template<
281     typename UserAllocator,
282     typename Mutex,
283     unsigned NextSize,
284     unsigned MaxSize>
285 class pool_allocator<void, UserAllocator, Mutex, NextSize, MaxSize>
286 {
287 public:
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>.
293     //!
294     //! Nested class rebind allows for transformation from
295     //! pool_allocator<T> to pool_allocator<U> via the member
296     //! typedef other.
297     template <class U> 
298     struct rebind
299     {
300        typedef pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
301     };
302 };
303
304 //! Simple tag type used by fast_pool_allocator as a template parameter to the underlying singleton_pool.
305 struct fast_pool_allocator_tag
306 {
307 };
308
309  /*! \brief A C++ Standard Library conforming allocator geared towards allocating single chunks.
310
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>.
316
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>.
320
321   The template parameters are defined as follows:
322
323   <b>T</b> Type of object to allocate/deallocate.
324
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.
327
328   <b>Mutex</b> Allows the user to determine the type of synchronization to be used on the underlying <tt>singleton_pool</tt>.
329
330   <b>NextSize</b> The value of this parameter is passed to the underlying Pool when it is created.
331
332   <b>MaxSize</b> Limit on the maximum size used.
333
334    \attention
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.
341  
342  */
343
344 template <typename T,
345     typename UserAllocator,
346     typename Mutex,
347     unsigned NextSize,
348     unsigned MaxSize >
349 class fast_pool_allocator
350 {
351   public:
352     typedef T value_type;
353     typedef UserAllocator user_allocator;
354     typedef Mutex mutex;
355     BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize);
356
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;
363
364     //! \brief Nested class rebind allows for transformation from
365     //! fast_pool_allocator<T> to fast_pool_allocator<U>.
366     //!
367     //! Nested class rebind allows for transformation from
368     //! fast_pool_allocator<T> to fast_pool_allocator<U> via the member
369     //! typedef other.
370     template <typename U>
371     struct rebind
372     {
373       typedef fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
374     };
375
376   public:
377     fast_pool_allocator()
378     {
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);
385     }
386
387     // Default copy constructor used.
388
389     // Default assignment operator used.
390
391     // Not explicit, mimicking std::allocator [20.4.1]
392     template <typename U>
393     fast_pool_allocator(
394         const fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> &)
395     {
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);
402     }
403
404     // Default destructor used.
405
406     static pointer address(reference r)
407     {
408       return &r;
409     }
410     static const_pointer address(const_reference s)
411     { return &s; }
412     static size_type max_size()
413     { return (std::numeric_limits<size_type>::max)(); }
414
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)...); }
419 #else
420     void construct(const pointer ptr, const value_type & t)
421     { new (ptr) T(t); }
422 #endif
423
424     void destroy(const pointer ptr)
425     { //! Destroy ptr using destructor.
426       ptr->~T();
427       (void) ptr; // Avoid unused variable warning.
428     }
429
430     bool operator==(const fast_pool_allocator &) const
431     { return true; }
432     bool operator!=(const fast_pool_allocator &) const
433     { return false; }
434
435     static pointer allocate(const size_type n)
436     {
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) );
444       if (ret == 0)
445         boost::throw_exception(std::bad_alloc());
446       return ret;
447     }
448     static pointer allocate(const size_type n, const void * const)
449     { //! Allocate memory .
450       return allocate(n);
451     }
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)() );
457       if (ret == 0)
458         boost::throw_exception(std::bad_alloc());
459       return ret;
460     }
461     static void deallocate(const pointer ptr, const size_type n)
462     { //! Deallocate memory.
463
464 #ifdef BOOST_NO_PROPER_STL_DEALLOCATE
465       if (ptr == 0 || n == 0)
466         return;
467 #endif
468       if (n == 1)
469         (singleton_pool<fast_pool_allocator_tag, sizeof(T),
470             UserAllocator, Mutex, NextSize, MaxSize>::free)(ptr);
471       else
472         (singleton_pool<fast_pool_allocator_tag, sizeof(T),
473             UserAllocator, Mutex, NextSize, MaxSize>::free)(ptr, n);
474     }
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);
479     }
480 };
481
482 /*!  \brief Specialization of fast_pool_allocator<void>.
483
484 Specialization of fast_pool_allocator<void> required to make the allocator standard-conforming.
485 */
486 template<
487     typename UserAllocator,
488     typename Mutex,
489     unsigned NextSize,
490     unsigned MaxSize >
491 class fast_pool_allocator<void, UserAllocator, Mutex, NextSize, MaxSize>
492 {
493 public:
494     typedef void*       pointer;
495     typedef const void* const_pointer;
496     typedef void        value_type;
497
498     //! \brief Nested class rebind allows for transformation from
499     //! fast_pool_allocator<T> to fast_pool_allocator<U>.
500     //!
501     //! Nested class rebind allows for transformation from
502     //! fast_pool_allocator<T> to fast_pool_allocator<U> via the member
503     //! typedef other.
504     template <class U> struct rebind
505     {
506         typedef fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
507     };
508 };
509
510 } // namespace boost
511
512 #endif