• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[/
2 / Copyright (c) 2000 - 2006 Stephen Cleary
3 / Copyright (c) 2011  Paul A. Bristow (conversion to Quickbook format)
4 / Distributed under the Boost Software License, Version 1.0.
5 / (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 /]
7
8[article Boost.Pool
9    [quickbook 1.5]
10    [authors [Cleary, Stephen]]
11    [copyright 2000 - 2006 Stephen Cleary, 2011 Paul A. Bristow]
12    [license
13        Distributed under the Boost Software License, Version 1.0.
14        (See accompanying file LICENSE_1_0.txt or copy at
15        [@http://www.boost.org/LICENSE_1_0.txt])
16    ]
17]
18
19[def __BoostPool__ [*Boost.Pool]]
20
21[def __inherit [*Inherits:]]
22[def __std_ref [*C++ Standard Reference:]]
23[def __header [*Header:]]
24[def __compat [*Compiler Compatibility:]]
25[def __examples [*Examples:]]
26[def __example [*Example:]]
27[def __type [*type:]]
28[def __returns [*Returns:]]
29[def __throws [*Throws:]]
30[def __remarks [*Remarks:]]
31[def __effects [*Effects:]]
32[def __post_conditions [*PostConditions:]]
33[def __pre_conditions [*PreConditions:]]
34[def __requires [*Requires:]]
35
36[def __pool_interfaces [link boost_pool.pool.interfaces Pool Interfaces]]
37[def __pool_interface [link boost_pool.pool.interfaces.pool Pool Interface]]
38[def __object_pool_interface [link boost_pool.pool.interfaces.object_pool Object Pool Interface]]
39[def __singleton_pool_interface [link boost_pool.pool.interfaces.singleton_pool Singleton Pool Interface]]
40[def __singleton_pool_exceptions_interface [link boost_pool.pool.interfaces.pool_alloc Singleton Pool with exceptions Interface]]
41
42[def __pool_references [link boost_pool.pool.appendices.references References]]
43[def __pool_concepts [link boost_pool.pool.pooling.concepts concepts]]
44[def __pool_simple_segregated_storage [link boost_pool.pool.pooling.simple Simple Segregated Storage]]
45
46[def __todo [link boost_pool.appendices.todo TODO]]
47[def __UserAllocator [link boost_pool.pool.pooling.user_allocator UserAllocator]]
48
49[template mu[]'''μ'''] [/ � Greek small letter mu]
50[template plusminus[]'''±'''] [/ plus or minus sign]
51
52[template graphic[name]
53'''
54<inlinemediaobject>
55<imageobject role="html">
56<imagedata align="center" fileref="../images/'''[name]'''.png"></imagedata>
57</imageobject>
58<imageobject role="print">
59<imagedata align="center" fileref="../images/'''[name]'''.svg"></imagedata>
60</imageobject>
61</inlinemediaobject>
62''']
63
64[section:pool Introduction and Overview]
65
66[section:conventions Documentation Naming and Formatting Conventions]
67
68This documentation makes use of the following naming and formatting conventions.
69
70* Code is in `fixed width font` and is syntax-highlighted in color.
71* Replaceable text that you will need to supply is in [~italics].
72* Free functions are rendered in the `code font` followed by `()`, as in `free_function()`.
73* If a name refers to a class template, it is specified like this:   `class_template<>`; that is, it is in code font and its name is followed by `<>`   to indicate that it is a class template.
74* If a name refers to a function-like macro, it is specified like this: `MACRO()`;
75  that is, it is uppercase in code font and its name is followed by `()` to   indicate that it is a function-like macro. Object-like macros appear without the   trailing `()`.
76* Names that refer to /concepts/ in the generic programming sense are  specified in CamelCase.
77
78[note In addition, notes such as this one specify non-essential information that provides additional background or rationale.]
79
80Finally, you can mentally add the following to any code fragments in this document:
81
82    // Include all of Pool files
83    #include <boost/pool.hpp>
84
85[endsect] [/section:conventions Documentation Naming and Formatting Conventions]
86
87[section:introduction Introduction]
88[h5 What is Pool?]
89
90Pool allocation is a memory allocation scheme that is very fast, but limited in its usage.
91For more information on pool allocation (also called ['simple segregated storage],
92see __pool_concepts concepts and __pool_simple_segregated_storage).
93
94[h5 Why should I use Pool?]
95
96Using Pools gives you more control over how memory is used in your program.
97For example, you could have a situation where you want to allocate a
98bunch of small objects at one point, and then reach a point in your program
99where none of them are needed any more. Using pool interfaces,
100you can choose to run their destructors or just drop them off into oblivion;
101the pool interface will guarantee that there are no system memory leaks.
102
103[h5 When should I use Pool?]
104
105Pools are generally used when there is a lot of allocation and deallocation of small objects.
106Another common usage is the situation above, where many objects may be dropped out of memory.
107
108In general, use Pools when you need a more efficient way to do unusual memory control.
109
110[h5 Which pool allocator should I use?]
111
112`pool_allocator` is a more general-purpose solution, geared towards
113efficiently servicing requests for any number of contiguous chunks.
114
115`fast_pool_allocator` is also a general-purpose solution
116but is geared towards efficiently servicing requests for one chunk at a time;
117it will work for contiguous chunks, but not as well as pool_allocator.
118
119If you are seriously concerned about performance,
120use `fast_pool_allocator` when dealing with containers such as `std::list`,
121and use `pool_allocator` when dealing with containers such as `std::vector`.
122
123[endsect] [/section:introduction Introduction]
124
125[section:usage How do I use Pool?]
126
127See the __pool_interfaces section that covers the different Pool interfaces supplied by this library.
128
129[h5 Library Structure and Dependencies]
130
131Forward declarations of all the exposed symbols for this library
132are in the header made inscope by `#include <boost/pool/poolfwd.hpp>`.
133
134The library may use macros, which will be prefixed with `BOOST_POOL_`.
135The exception to this rule are the include file guards,
136which (for file `xxx.hpp`) is `BOOST_xxx_HPP`.
137
138All exposed symbols defined by the library will be in namespace boost::.
139All symbols used only by the implementation will be in namespace boost::details::pool.
140
141Every header used only by the implementation is in the subdirectory `/detail/`.
142
143Any header in the library may include any other header in the library
144or any system-supplied header at its discretion.
145
146[endsect] [/section:usage How do I use Pool?]
147
148[section:installation Installation]
149
150The Boost Pool library is a header-only library.
151That means there is no .lib, .dll, or .so to build;
152just add the Boost directory to your compiler's include file path,
153and you should be good to go!
154
155[endsect] [/section:installation Installation]
156
157[section:testing Building the Test Programs]
158
159A jamfile.v2 is provided which can be run is the usual way, for example:
160
161``boost\libs\pool\test> bjam -a >pool_test.log``
162
163[endsect] [/section:testing Building the Test Programs]
164
165[section:interfaces Boost Pool Interfaces - What interfaces are provided and when to use each one.]
166
167[h4 Introduction]
168
169There are several interfaces provided which allow users great flexibility
170in how they want to use Pools.
171Review the __pool_concepts document to get the basic understanding of how the various pools work.
172
173[h3 Terminology and Tradeoffs]
174
175[h5 Object Usage vs. Singleton Usage]
176
177Object Usage is the method where each Pool is an object that may be created and destroyed.
178Destroying a Pool implicitly frees all chunks that have been allocated from it.
179
180Singleton Usage is the method where each Pool is an object with static duration;
181that is, it will not be destroyed until program exit.
182Pool objects with Singleton Usage may be shared;
183thus, Singleton Usage implies thread-safety as well.
184System memory allocated by Pool objects with Singleton Usage
185may be freed through release_memory or purge_memory.
186
187[h5 Out-of-Memory Conditions: Exceptions vs. Null Return]
188
189Some Pool interfaces throw exceptions when out-of-memory;
190others will `return 0`. In general, unless mandated by the Standard,
191Pool interfaces will always prefer to `return 0` instead of throwing an exception.
192
193[h5 Ordered versus unordered]
194
195An ordered pool maintains it's free list in order of the address of each free block -
196this is the most efficient way if you're likely to allocate arrays of objects.
197However, freeing an object can be O(N) in the number of currently free blocks which
198can be prohibitively expensive in some situations.
199
200An unordered pool does not maintain it's free list in any particular order, as a result
201allocation and freeing single objects is very fast, but allocating arrays may be slow
202(and in particular the pool may not be aware that it contains enough free memory for the
203allocation request, and unnecessarily allocate more memory).
204
205[section:interfaces Pool Interfaces]
206
207[section:pool pool]
208
209The [classref boost::pool pool]
210interface is a simple Object Usage interface with Null Return.
211
212[classref boost::pool pool] is a fast memory allocator,
213and guarantees proper alignment of all allocated chunks.
214
215[headerref boost/pool/pool.hpp pool.hpp] provides two __UserAllocator classes
216and a [classref boost::pool template class pool],
217which extends and generalizes the framework provided by the
218__pool_simple_segregated_storage solution.
219For information on other pool-based interfaces, see the other __pool_interfaces.
220
221[*Synopsis]
222
223There are two __UserAllocator classes provided.
224Both of them are in [headerref boost/pool/pool.hpp pool.hpp].
225
226The default value for the template parameter __UserAllocator is always
227`default_user_allocator_new_delete`.
228
229``
230  struct default_user_allocator_new_delete
231  {
232    typedef std::size_t size_type;
233    typedef std::ptrdiff_t difference_type;
234
235    static char * malloc(const size_type bytes)
236    { return new (std::nothrow) char[bytes]; }
237    static void free(char * const block)
238    { delete [] block; }
239  };
240
241  struct default_user_allocator_malloc_free
242  {
243    typedef std::size_t size_type;
244    typedef std::ptrdiff_t difference_type;
245
246    static char * malloc(const size_type bytes)
247    { return reinterpret_cast<char *>(std::malloc(bytes)); }
248    static void free(char * const block)
249    { std::free(block); }
250  };
251
252  template <typename UserAllocator = default_user_allocator_new_delete>
253  class pool
254  {
255    private:
256      pool(const pool &);
257      void operator=(const pool &);
258
259    public:
260      typedef UserAllocator user_allocator;
261      typedef typename UserAllocator::size_type size_type;
262      typedef typename UserAllocator::difference_type difference_type;
263
264      explicit pool(size_type requested_size);
265      ~pool();
266
267      bool release_memory();
268      bool purge_memory();
269
270      bool is_from(void * chunk) const;
271      size_type get_requested_size() const;
272
273      void * malloc();
274      void * ordered_malloc();
275      void * ordered_malloc(size_type n);
276
277      void free(void * chunk);
278      void ordered_free(void * chunk);
279      void free(void * chunks, size_type n);
280      void ordered_free(void * chunks, size_type n);
281  };
282``
283
284[*Example:]
285``
286void func()
287{
288  boost::pool<> p(sizeof(int));
289  for (int i = 0; i < 10000; ++i)
290  {
291    int * const t = p.malloc();
292    ... // Do something with t; don't take the time to free() it.
293  }
294} // on function exit, p is destroyed, and all malloc()'ed ints are implicitly freed.
295``
296
297[endsect] [/section pool]
298
299
300[section:object_pool Object_pool]
301
302The [classref boost::object_pool template class object_pool]
303interface is an Object Usage interface with Null Return,
304but is aware of the type of the object for which it is allocating chunks.
305On destruction, any chunks that have been allocated
306from that `object_pool` will have their destructors called.
307
308[headerref  boost/pool/object_pool.hpp object_pool.hpp]
309provides a template type that can be used for fast and efficient memory allocation.
310It also provides automatic destruction of non-deallocated objects.
311
312For information on other pool-based interfaces, see the other __pool_interfaces.
313
314[*Synopsis]
315
316``template <typename ElementType, typename UserAllocator = default_user_allocator_new_delete>
317class object_pool
318{
319  private:
320    object_pool(const object_pool &);
321    void operator=(const object_pool &);
322
323  public:
324    typedef ElementType element_type;
325    typedef UserAllocator user_allocator;
326    typedef typename pool<UserAllocator>::size_type size_type;
327    typedef typename pool<UserAllocator>::difference_type difference_type;
328
329    object_pool();
330    ~object_pool();
331
332    element_type * malloc();
333    void free(element_type * p);
334    bool is_from(element_type * p) const;
335
336    element_type * construct();
337    // other construct() functions
338    void destroy(element_type * p);
339};
340``
341[*Template Parameters]
342
343['ElementType]
344
345The template parameter is the type of object to allocate/deallocate.
346It must have a non-throwing destructor.
347
348['UserAllocator]
349
350Defines the method that the underlying Pool will use to allocate memory from the system.
351Default is default_user_allocator_new_delete.  See ____UserAllocator for details.
352
353[*Example:]
354  struct X { ... }; // has destructor with side-effects.
355
356  void func()
357  {
358    boost::object_pool<X> p;
359    for (int i = 0; i < 10000; ++i)
360    {
361      X * const t = p.malloc();
362      ... // Do something with t; don't take the time to free() it.
363    }
364  } // on function exit, p is destroyed, and all destructors for the X objects are called.
365
366[endsect] [/section object_pool]
367
368[section:singleton_pool Singleton_pool]
369
370The [classref boost::singleton_pool singleton_pool interface]
371at [headerref boost/pool/singleton_pool.hpp singleton_pool.hpp]
372is a Singleton Usage interface with Null Return.
373It's just the same as the pool interface but with Singleton Usage instead.
374
375[*Synopsis]
376
377``template <typename Tag, unsigned RequestedSize,
378    typename UserAllocator = default_user_allocator_new_delete>
379struct singleton_pool
380{
381  public:
382    typedef Tag tag;
383    typedef UserAllocator user_allocator;
384    typedef typename pool<UserAllocator>::size_type size_type;
385    typedef typename pool<UserAllocator>::difference_type difference_type;
386
387    static const unsigned requested_size = RequestedSize;
388
389  private:
390    static pool<size_type> p; // exposition only!
391
392    singleton_pool();
393
394  public:
395    static bool is_from(void * ptr);
396
397    static void * malloc();
398    static void * ordered_malloc();
399    static void * ordered_malloc(size_type n);
400
401    static void free(void * ptr);
402    static void ordered_free(void * ptr);
403    static void free(void * ptr, std::size_t n);
404    static void ordered_free(void * ptr, size_type n);
405
406    static bool release_memory();
407    static bool purge_memory();
408};
409``
410[*Notes]
411
412The underlying pool `p` referenced by the static functions in `singleton_pool`
413is actually declared in a way so that it is:
414
415* Thread-safe if there is only one thread running before `main()` begins and after `main()` ends. All of the static functions of singleton_pool synchronize their access to `p`.
416* Guaranteed to be constructed before it is used, so that the simple static object in the synopsis above would actually be an incorrect implementation. The actual implementation to guarantee this is considerably more complicated.
417
418[*Note] that a different underlying pool `p` exists for each different set of template parameters, including implementation-specific ones.
419
420[*Template Parameters]
421
422['Tag]
423
424The ['Tag] template parameter allows different unbounded sets of singleton pools to exist.
425For example, the pool allocators use two tag classes to ensure that the two different
426 allocator types never share the same underlying singleton pool.
427
428['Tag] is never actually used by `singleton_pool`.
429
430['RequestedSize]
431The requested size of memory chunks to allocate.
432This is passed as a constructor parameter to the underlying pool.
433Must be greater than 0.
434
435['UserAllocator]
436
437Defines the method that the underlying pool will use to allocate memory from the system. See User Allocators for details.
438
439[*Example:]
440  struct MyPoolTag { };
441
442  typedef boost::singleton_pool<MyPoolTag, sizeof(int)> my_pool;
443  void func()
444  {
445    for (int i = 0; i < 10000; ++i)
446    {
447      int * const t = my_pool::malloc();
448      ... // Do something with t; don't take the time to free() it.
449    }
450    // Explicitly free all malloc()'ed ints.
451    my_pool::purge_memory();
452  }
453[endsect] [/section singleton_pool]
454
455[section:pool_allocator pool_allocator]
456
457The [classref boost::pool_allocator pool_allocator interface]
458is a Singleton Usage interface with Exceptions.
459It is built on the singleton_pool interface,
460and provides a Standard Allocator-compliant class (for use in containers, etc.).
461
462[*Introduction]
463
464[headerref boost/pool/pool_alloc.hpp pool_alloc.hpp]
465
466Provides two template types that can be used for fast and efficient memory allocation.
467These types both satisfy the Standard Allocator requirements [20.1.5]
468and the additional requirements in [20.1.5/4],
469so they can be used with Standard or user-supplied containers.
470
471For information on other pool-based interfaces, see the other __pool_interfaces.
472
473[*Synopsis]
474
475``
476struct pool_allocator_tag { };
477
478template <typename T,
479    typename UserAllocator = default_user_allocator_new_delete>
480class pool_allocator
481{
482  public:
483    typedef UserAllocator user_allocator;
484    typedef T value_type;
485    typedef value_type * pointer;
486    typedef const value_type * const_pointer;
487    typedef value_type & reference;
488    typedef const value_type & const_reference;
489    typedef typename pool<UserAllocator>::size_type size_type;
490    typedef typename pool<UserAllcoator>::difference_type difference_type;
491
492    template <typename U>
493    struct rebind
494    { typedef pool_allocator<U, UserAllocator> other; };
495
496  public:
497    pool_allocator();
498    pool_allocator(const pool_allocator &);
499    // The following is not explicit, mimicking std::allocator [20.4.1]
500    template <typename U>
501    pool_allocator(const pool_allocator<U, UserAllocator> &);
502    pool_allocator & operator=(const pool_allocator &);
503    ~pool_allocator();
504
505    static pointer address(reference r);
506    static const_pointer address(const_reference s);
507    static size_type max_size();
508    static void construct(pointer ptr, const value_type & t);
509    static void destroy(pointer ptr);
510
511    bool operator==(const pool_allocator &) const;
512    bool operator!=(const pool_allocator &) const;
513
514    static pointer allocate(size_type n);
515    static pointer allocate(size_type n, pointer);
516    static void deallocate(pointer ptr, size_type n);
517};
518
519struct fast_pool_allocator_tag { };
520
521template <typename T
522    typename UserAllocator = default_user_allocator_new_delete>
523class fast_pool_allocator
524{
525  public:
526    typedef UserAllocator user_allocator;
527    typedef T value_type;
528    typedef value_type * pointer;
529    typedef const value_type * const_pointer;
530    typedef value_type & reference;
531    typedef const value_type & const_reference;
532    typedef typename pool<UserAllocator>::size_type size_type;
533    typedef typename pool<UserAllocator>::difference_type difference_type;
534
535    template <typename U>
536    struct rebind
537    { typedef fast_pool_allocator<U, UserAllocator> other; };
538
539  public:
540    fast_pool_allocator();
541    fast_pool_allocator(const fast_pool_allocator &);
542    // The following is not explicit, mimicking std::allocator [20.4.1]
543    template <typename U>
544    fast_pool_allocator(const fast_pool_allocator<U, UserAllocator> &);
545    fast_pool_allocator & operator=(const fast_pool_allocator &);
546    ~fast_pool_allocator();
547
548    static pointer address(reference r);
549    static const_pointer address(const_reference s);
550    static size_type max_size();
551    static void construct(pointer ptr, const value_type & t);
552    static void destroy(pointer ptr);
553
554    bool operator==(const fast_pool_allocator &) const;
555    bool operator!=(const fast_pool_allocator &) const;
556
557    static pointer allocate(size_type n);
558    static pointer allocate(size_type n, pointer);
559    static void deallocate(pointer ptr, size_type n);
560
561    static pointer allocate();
562    static void deallocate(pointer ptr);
563};
564``
565[*Template Parameters]
566
567['T]  The first template parameter is the type of object to allocate/deallocate.
568
569['UserAllocator]  Defines the method that the underlying Pool will use to allocate memory from the system.
570See User Allocators for details.
571
572[*Example:]
573
574  void func()
575  {
576    std::vector<int, boost::pool_allocator<int> > v;
577    for (int i = 0; i < 10000; ++i)
578      v.push_back(13);
579  } // Exiting the function does NOT free the system memory allocated by the pool allocator.
580    // You must call
581    //  boost::singleton_pool<boost::pool_allocator_tag, sizeof(int)>::release_memory();
582    // in order to force freeing the system memory.
583
584[endsect] [/section pool_alloc]
585
586[endsect] [/section:interfaces The Interfaces - pool, object_pool and singleton_pool]
587
588[endsect] [/section:interfaces- What interfaces are provided and when to use each one.]
589
590[section:pooling Pool in More Depth]
591
592[section:concepts Basic ideas behind pooling]
593
594['Dynamic memory allocation has been a fundamental part
595of most computer systems since roughly 1960...] [link ref1 1]
596
597Everyone uses dynamic memory allocation.
598If you have ever called malloc or new, then you have used dynamic memory allocation.
599Most programmers have a tendency to treat the heap as a ["magic bag"]:
600we ask it for memory, and it magically creates some for us.
601Sometimes we run into problems because the heap is not magic.
602
603The heap is limited.
604Even on large systems (i.e., not embedded) with huge amounts of virtual memory available,
605there is a limit. Everyone is aware of the physical limit,
606but there is a more subtle, 'virtual' limit, that limit at which your program
607(or the entire system) slows down due to the use of virtual memory.
608This virtual limit is much closer to your program than the physical limit,
609especially if you are running on a multitasking system.
610Therefore, when running on a large system, it is considered ['nice]
611to make your program use as few resources as necessary, and release them as soon as possible.
612When using an embedded system, programmers usually have no memory to waste.
613
614The heap is complicated.
615It has to satisfy any type of memory request, for any size, and do it fast.
616The common approaches to memory management have to do with splitting the memory up into portions,
617and keeping them ordered by size in some sort of a tree or list structure. Add in other factors,
618such as locality and estimating lifetime, and heaps quickly become very complicated.
619So complicated, in fact, that there is no known ['perfect] answer to the
620problem of how to do dynamic memory allocation.
621The diagrams below illustrate how most common memory managers work: for each chunk of memory,
622it uses part of that memory to maintain its internal tree or list structure.
623Even when a chunk is malloc'ed out to a program, the memory manager
624must ['save] some information in it - usually just its size.
625Then, when the block is free'd, the memory manager can easily tell how large it is.
626
627[graphic pc1]
628
629[graphic pc2]
630
631[h5 Dynamic memory allocation is often inefficient]
632
633Because of the complication of dynamic memory allocation,
634it is often inefficient in terms of time and/or space.
635Most memory allocation algorithms store some form of information with each memory block,
636either the block size or some relational information,
637such as its position in the internal tree or list structure.
638It is common for such ['header fields] to take up one machine word in a block
639that is being used by the program. The obvious disadvantage, then,
640is when small objects are dynamically allocated.
641For example, if ints were dynamically allocated,
642then automatically the algorithm will reserve space for the header fields as well,
643and we end up with a 50% waste of memory. Of course, this is a worst-case scenario.
644However, more modern programs are making use of small objects on the heap;
645and that is making this problem more and more apparent. Wilson et. al. state that
646an average-case memory overhead is about ten to twenty percent[@#ref2 2].
647This memory overhead will grow higher as more programs use more smaller objects.
648It is this memory overhead that brings programs closer to the virtual limit.
649
650In larger systems, the memory overhead is not as big of a problem
651(compared to the amount of time it would take to work around it),
652and thus is often ignored. However, there are situations
653where many allocations and/or deallocations of smaller objects
654are taking place as part of a time-critical algorithm, and in these situations,
655the system-supplied memory allocator is often too slow.
656
657Simple segregated storage addresses both of these issues.
658Almost all memory overhead is done away with, and all allocations can take place
659in a small amount of (amortized) constant time.
660However, this is done at the loss of generality;
661simple segregated storage only can allocate memory chunks of a single size.
662
663[endsect] [/section:concepts Basic ideas behind pooling]
664
665[section:simple Simple Segregated Storage]
666
667Simple Segregated Storage is the basic idea behind the Boost Pool library.
668Simple Segregated Storage is the simplest, and probably the fastest,
669memory allocation/deallocation algorithm.
670It begins by partitioning a memory block into fixed-size chunks.
671Where the block comes from is not important until implementation time.
672A Pool is some object that uses Simple Segregated Storage in this fashion.
673To illustrate:
674
675[graphic pc3]
676
677Each of the chunks in any given block are always the same size.
678This is the fundamental restriction of Simple Segregated Storage:
679you cannot ask for chunks of different sizes.
680For example, you cannot ask a Pool of integers for a character,
681or a Pool of characters for an integer
682(assuming that characters and integers are different sizes).
683
684Simple Segregated Storage works by interleaving a free list within the unused chunks.
685For example:
686
687[graphic pc4]
688
689By interleaving the free list inside the chunks,
690each Simple Segregated Storage only has the overhead of a single pointer
691(the pointer to the first element in the list).
692It has no memory overhead for chunks that are in use by the process.
693
694Simple Segregated Storage is also extremely fast.
695In the simplest case, memory allocation is merely
696removing the first chunk from the free list,
697a O(1) operation. In the case where the free list is empty,
698another block may have to be acquired and partitioned,
699which would result in an amortized O(1) time.
700Memory deallocation may be as simple as adding that chunk
701to the front of the free list, a O(1) operation.
702However, more complicated uses of Simple Segregated Storage may require a sorted free list,
703which makes deallocation O(N).
704
705[graphic pc5]
706
707Simple Segregated Storage gives faster execution and less memory overhead
708than a system-supplied allocator, but at the loss of generality.
709A good place to use a Pool is in situations
710where many (noncontiguous) small objects may be allocated on the heap,
711or if allocation and deallocation of the same-sized objects happens repeatedly.
712
713[endsect] [/section:simple Simple Segregated Storage]
714
715[section:alignment Guaranteeing Alignment - How we guarantee alignment portably.]
716
717[h4 Terminology]
718
719Review the __pool_concepts section if you are not already familiar with it.
720Remember that block is a contiguous section of memory,
721which is partitioned or segregated into fixed-size chunks.
722These chunks are what are allocated and deallocated by the user.
723
724[h4 Overview]
725
726Each Pool has a single free list that can extend over a number of memory blocks.
727Thus, Pool also has a linked list of allocated memory blocks.
728Each memory block, by default, is allocated using `new[]`,
729and all memory blocks are freed on destruction.
730It is the use of `new[]` that allows us to guarantee alignment.
731
732[h4 Proof of Concept: Guaranteeing Alignment]
733
734Each block of memory is allocated as a POD type
735(specifically, an array of characters) through `operator new[]`.
736Let `POD_size` be the number of characters allocated.
737
738[h5 Predicate 1: Arrays may not have padding]
739
740This follows from the following quote:
741
742[5.3.3/2] (Expressions::Unary expressions::Sizeof)
743['... When applied to an array, the result is the total number of bytes in the array.
744This implies that the size of an array of n elements is n times the size of an element.]
745
746Therefore, arrays cannot contain padding,
747though the elements within the arrays may contain padding.
748
749[h5 Predicate 2: Any block of memory allocated as an array of characters through `operator new[]`
750(hereafter referred to as the block) is properly aligned for any object of that size or smaller]
751
752This follows from:
753
754* [3.7.3.1/2] (Basic concepts::Storage duration::Dynamic storage duration::Allocation functions)
755['"... The pointer returned shall be suitably aligned
756so that it can be converted to a pointer of any complete object type
757and then used to access the object or array in the storage allocated ..."]
758* [5.3.4/10] (Expressions::Unary expressions::New)
759['"... For arrays of char and unsigned char,
760the difference between the result of the new-expression and
761the address returned by the allocation function shall be an integral multiple
762of the most stringent alignment requirement (3.9) of any object type whose size
763is no greater than the size of the array being created.
764[Note: Because allocation functions are assumed to return pointers to storage
765that is appropriately aligned for objects of any type,
766this constraint on array allocation overhead permits
767the common idiom of allocating character arrays
768into which objects of other types will later be placed."]
769
770[h5 Consider: imaginary object type Element of a size which is a
771multiple of some actual object size; assume `sizeof(Element) > POD_size`]
772
773Note that an object of that size can exist.
774One object of that size is an array of the "actual" objects.
775
776Note that the block is properly aligned for an Element.
777This directly follows from Predicate 2.
778
779[h5 Corollary 1: The block is properly aligned for an array of Elements]
780
781This follows from Predicates 1 and 2, and the following quote:
782
783[3.9/9] (Basic concepts::Types)
784['"An object type is a (possibly cv-qualified) type that is not a function type,
785not a reference type, and not a void type."]
786
787(Specifically, array types are object types.)
788
789[h5 Corollary 2: For any pointer `p` and integer `i`,
790if `p` is properly aligned for the type it points to, then `p + i` (when well-defined)
791is properly aligned for that type; in other words, if an array is properly aligned,
792then each element in that array is properly aligned]
793
794There are no quotes from the Standard to directly support this argument,
795but it fits the common conception of the meaning of "alignment".
796
797Note that the conditions for `p + i` being well-defined are outlined in [5.7/5].
798We do not quote that here, but only make note that it is well-defined
799if `p` and `p + i` both point into or one past the same array.
800
801[h5 Let: `sizeof(Element)` be the least common multiple of sizes
802of several actual objects (T1, T2, T3, ...)]
803
804[h5 Let: block be a pointer to the memory block,
805pe be (Element *) block, and pn be (Tn *) block]
806
807[h5 Corollary 3: For each integer `i`, such that `pe + i` is well-defined,
808then for each n, there exists some integer `jn` such that `pn + jn` is well-defined
809and refers to the same memory address as `pe + i`]
810
811This follows naturally, since the memory block is an array of Elements,
812and for each n, `sizeof(Element) % sizeof(Tn) == 0;`
813thus, the boundary of each element in the array of Elements
814is also a boundary of each element in each array of Tn.
815
816[h5 Theorem: For each integer `i`, such that `pe + i` is well-defined,
817that address (pe + i) is properly aligned for each type Tn]
818
819Since `pe + i` is well-defined, then by Corollary 3, `pn + jn` is well-defined.
820It is properly aligned from Predicate 2 and Corollaries 1 and 2.
821
822[h4 Use of the Theorem]
823
824The proof above covers alignment requirements for cutting chunks out of a block.
825The implementation uses actual object sizes of:
826
827* The requested object size (`requested_size`); this is the size of chunks requested by the user
828* `void*` (pointer to void); this is because we interleave our free list through the chunks
829* `size_type`; this is because we store the size of the next block within each memory block
830
831Each block also contains a pointer to the next block;
832but that is stored as a pointer to void and cast when necessary,
833to simplify alignment requirements to the three types above.
834
835Therefore, `alloc_size` is defined to be the largest of the sizes above, rounded up to be a multiple
836of all three sizes.  This guarantees alignment provided all alignments are powers of two: something that
837appears to be true on all known platforms.
838
839[h4 A Look at the Memory Block]
840
841Each memory block consists of three main sections.
842The first section is the part that chunks are cut out of,
843and contains the interleaved free list.
844The second section is the pointer to the next block,
845and the third section is the size of the next block.
846
847Each of these sections may contain padding as necessary
848to guarantee alignment for each of the next sections.
849The size of the first section is `number_of_chunks * lcm(requested_size, sizeof(void *), sizeof(size_type));`
850the size of the second section is `lcm(sizeof(void *), sizeof(size_type);`
851and the size of the third section is `sizeof(size_type)`.
852
853Here's an example memory block, where `requested_size == sizeof(void *) == sizeof(size_type) == 4`:
854
855[graphic mb1]
856
857To show a visual example of possible padding,
858here's an example memory block where
859`requested_size == 8 and sizeof(void *) == sizeof(size_type) == 4`
860
861[graphic mb2]
862
863[section:chunks How Contiguous Chunks are Handled]
864
865The theorem above guarantees all alignment requirements for allocating chunks
866and also implementation details such as the interleaved free list.
867However, it does so by adding padding when necessary;
868therefore, we have to treat allocations of contiguous chunks in a different way.
869
870Using array arguments similar to the above,
871we can translate any request for contiguous memory for `n` objects of `requested_size`
872into a request for m contiguous chunks.
873`m` is simply `ceil(n * requested_size / alloc_size)`,
874where `alloc_size` is the actual size of the chunks.
875
876To illustrate:
877
878Here's an example memory block,
879where `requested_size == 1` and `sizeof(void *) == sizeof(size_type) == 4`:
880
881[graphic mb4]
882
883Then, when the user deallocates the contiguous memory,
884we can split it up into chunks again.
885
886Note that the implementation provided for allocating contiguous chunks
887uses a linear instead of quadratic algorithm.
888This means that it may not find contiguous free chunks if the free list is not ordered.
889Thus, it is recommended to always use an ordered free list
890when dealing with contiguous allocation of chunks.
891(In the example above, if Chunk 1 pointed to Chunk 3 pointed to Chunk 2 pointed to Chunk 4,
892instead of being in order,
893the contiguous allocation algorithm would have failed to find any of the contiguous chunks).
894
895[endsect] [/section:chunks How Contiguous Chunks are Handled]
896
897[endsect] [/section:alignment  Guaranteeing Alignment - How we guarantee alignment portably.]
898
899[section:simple_segregated Simple Segregated Storage (Not for the faint of heart - Embedded programmers only!)]
900
901[h4 Introduction]
902
903[headerref boost/pool/simple_segregated_storage.hpp simple_segregated_storage.hpp]
904provides a template class simple_segregated_storage
905that controls access to a free list of memory chunks.
906
907Note that this is a very simple class, with unchecked preconditions on almost all its functions.
908It is intended to be the fastest and smallest possible quick memory allocator
909for example, something to use in embedded systems.
910This class delegates many difficult preconditions to the user (especially alignment issues).
911For more general usage, see the other __pool_interfaces.
912
913[h4 Synopsis]
914[pre
915template <typename SizeType = std::size_t>
916class simple_segregated_storage
917{
918  private:
919    simple_segregated_storage(const simple_segregated_storage &);
920    void operator=(const simple_segregated_storage &);
921
922  public:
923    typedef SizeType size_type;
924
925    simple_segregated_storage();
926    ~simple_segregated_storage();
927
928    static void * segregate(void * block,
929        size_type nsz, size_type npartition_sz,
930        void * end = 0);
931    void add_block(void * block,
932        size_type nsz, size_type npartition_sz);
933    void add_ordered_block(void * block,
934        size_type nsz, size_type npartition_sz);
935
936    bool empty() const;
937
938    void * malloc();
939    void free(void * chunk);
940    void ordered_free(void * chunk);
941    void * malloc_n(size_type n, size_type partition_sz);
942    void free_n(void * chunks, size_type n,
943        size_type partition_sz);
944    void ordered_free_n(void * chunks, size_type n,
945        size_type partition_sz);
946};
947]
948
949[h4 Semantics]
950
951An object of type `simple_segregated_storage<SizeType>`
952is empty if its free list is empty.
953If it is not empty, then it is ordered if its free list is ordered.
954A free list is ordered if repeated calls to` malloc()` will result in
955a constantly-increasing sequence of values, as determined by `std::less<void *>`.
956A member function is order-preserving if the free-list maintains its order orientation
957(that is, an ordered free list is still ordered after the member function call).
958
959[table:ss_symbols Symbol Table
960[[Symbol] [Meaning] ]
961[[Store] [simple_segregated_storage<SizeType>]]
962[[t] [value of type Store]]
963[[u] [value of type const Store]]
964[[block, chunk, end] [values of type void *]]
965[[partition_sz, sz, n] [values of type Store::size_type]]
966]
967
968[table:templates Template Parameters
969[[Parameter] [Default] [Requirements]]
970[[SizeType] [std::size_t] [An unsigned integral type]]
971]
972
973[table:Typedefs Typedefs
974[[Symbol] [Type]]
975[[size_type] [SizeType]]
976]
977
978[table:Constructors Constructors, Destructors, and State
979[[Expression] [Return Type] [Post-Condition] [Notes]]
980[[Store()] [not used] [empty()] [Constructs a new Store]]
981[[(&t)->~Store()] [not used] [] [Destructs the Store]]
982[[u.empty()] [bool] [] [Returns true if u is empty. Order-preserving.]]
983]
984
985[table:Segregation Segregation
986[ [Expression] [Return Type] [Pre-Condition] [Post-Condition] [Semantic Equivalence] [Notes] ]
987[ [Store::segregate(block, sz, partition_sz, end)] [void *] [partition_sz >= sizeof(void *)
988partition_sz = sizeof(void *) * i, for some integer i
989sz >= partition_sz
990block is properly aligned for an array of objects of size partition_sz
991block is properly aligned for an array of void *] [] [] [Interleaves a free list through the memory block specified by block of size sz bytes, partitioning it into as many partition_sz-sized chunks as possible. The last chunk is set to point to end, and a pointer to the first chunck is returned (this is always equal to block). This interleaved free list is ordered. O(sz).] ]
992[ [Store::segregate(block, sz, partition_sz)] [void *] [Same as above] [] [Store::segregate(block, sz, partition_sz, 0)] [] ]
993[ [t.add_block(block, sz, partition_sz)] [void] [Same as above] [!t.empty()] [] [Segregates the memory block specified by block of size sz bytes into partition_sz-sized chunks, and adds that free list to its own. If t was empty before this call, then it is ordered after this call. O(sz).] ]
994[ [t.add_ordered_block(block, sz, partition_sz)] [void] [Same as above] [!t.empty()] [] [Segregates the memory block specified by block of size sz bytes into partition_sz-sized chunks, and merges that free list into its own. Order-preserving. O(sz).] ]
995]
996
997[table:alloc Allocation and Deallocation
998[ [Expression] [Return Type] [Pre-Condition] [Post-Condition] [Semantic Equivalence] [Notes] ]
999[ [t.malloc()] [void *] [!t.empty()] [] [] [Takes the first available chunk from the free list and returns it. Order-preserving. O(1).] ]
1000[ [t.free(chunk)] [void] [chunk was previously returned from a call to t.malloc()] [!t.empty()] [] [Places chunk back on the free list. Note that chunk may not be 0. O(1).] ]
1001[ [t.ordered_free(chunk)] [void] [Same as above] [!t.empty()] [] [Places chunk back on the free list. Note that chunk may not be 0. Order-preserving. O(N) with respect to the size of the free list.] ]
1002[ [t.malloc_n(n, partition_sz)] [void *] [] [] [] [Attempts to find a contiguous sequence of n partition_sz-sized chunks. If found, removes them all from the free list and returns a pointer to the first. If not found, returns 0. It is strongly recommended (but not required) that the free list be ordered, as this algorithm will fail to find a contiguous sequence unless it is contiguous in the free list as well. Order-preserving. O(N) with respect to the size of the free list.] ]
1003[ [t.free_n(chunk, n, partition_sz)] [void] [chunk was previously returned from a call to t.malloc_n(n, partition_sz)] [!t.empty()] [t.add_block(chunk, n * partition_sz, partition_sz)] [Assumes that chunk actually refers to a block of chunks spanning n * partition_sz bytes; segregates and adds in that block. Note that chunk may not be 0. O(n).] ]
1004[ [t.ordered_free_n(chunk, n, partition_sz)] [void] [same as above] [same as above] [t.add_ordered_block(chunk, n * partition_sz, partition_sz)] [Same as above, except it merges in the free list. Order-preserving. O(N + n) where N is the size of the free list.] ]
1005]
1006
1007[endsect] [/section:simple_segregated_storage]
1008
1009[section:user_allocator The UserAllocator Concept]
1010
1011Pool objects need to request memory blocks from the system, which the Pool then splits into chunks to allocate
1012to the user. By specifying a UserAllocator template parameter to various Pool interfaces, users can control how
1013those system memory blocks are allocated.
1014
1015In the following table, /UserAllocator/ is a User Allocator type,
1016/block/ is a value of type char *, and
1017/n/ is a value of type UserAllocator::size_type
1018
1019[table UserAllocator Requirements
1020[[Expression][Result][Description]]
1021[[UserAllocator::size_type][][An unsigned integral type that can represent the size of the largest object to be allocated.]]
1022[[UserAllocator::difference_type][][A signed integral type that can represent the difference of any two pointers.]]
1023[[UserAllocator::malloc(n)][char *][Attempts to allocate n bytes from the system. Returns 0 if out-of-memory.]]
1024[[UserAllocator::free(block)][void][block must have been previously returned from a call to UserAllocator::malloc.]]
1025]
1026
1027There are two UserAllocator classes provided in this library:
1028[classref boost::default_user_allocator_new_delete `default_user_allocator_new_delete`] and
1029[classref boost::default_user_allocator_malloc_free `default_user_allocator_malloc_free`],
1030both in pool.hpp. The default value for the template parameter UserAllocator is always
1031[classref boost::default_user_allocator_new_delete `default_user_allocator_new_delete`].
1032
1033[endsect][/section:user_allocator The UserAllocator Concept]
1034[endsect] [/section:pooling Pool in more depth]
1035
1036[endsect]
1037
1038[/Note that there will be always some warnings about the .ipp files in Doxygen warnings and Autodoxywarnings.log files.
1039"Warning: include file boost/pool/detail/pool_construct.ipp not found, perhaps you forgot to add its directory to INCLUDE_PATH?"
1040This is unavoidable because these must be included in the middle of the class declaration.
1041All the automatically generated constructors are documented in the Doxygen standalone version:
1042only the access to source files is missing.
1043The current Quickbook version does not deal with the /details directory so the problem does not arise
1044- unless the details files are included in future.]
1045
1046[/Note also that there is something funny about implementation class PODptr.
1047It is always necessary to qualify it thus "details::PODptr"
1048
1049and this confuses Doxygen complaining thus:
1050
1051Cannot find class named 'details::PODptr'
1052Cannot find class named 'details::PODptr'
1053Cannot find class named 'details::PODptr'
1054Cannot find class named 'details::PODptr'
1055
1056Attempts to avoid this with "using boost::details::PODptr;" have so far failed.
1057
1058]
1059
1060[xinclude autodoc.xml] [/ Boost.Pool Reference section, using Doxygen reference documentation.]
1061
1062
1063[/section:pool Introduction/Overview]
1064
1065[section:appendices Appendices]
1066
1067[section:history Appendix A: History]
1068
1069[h4 Version 2.0.0, January 11, 2011]
1070
1071['Documentation and testing revision]
1072
1073[*Features:]
1074
1075* Fix issues
1076[@https://svn.boost.org/trac/boost/ticket/1252 1252],
1077[@https://svn.boost.org/trac/boost/ticket/4960 4960],
1078[@https://svn.boost.org/trac/boost/ticket/5526 5526],
1079[@https://svn.boost.org/trac/boost/ticket/5700 5700],
1080[@https://svn.boost.org/trac/boost/ticket/2696 2696].
1081
1082* Documentation converted and rewritten and revised
1083by Paul A. Bristow using Quickbook, Doxygen, for html and pdf,
1084based on Stephen Cleary's html version, Revised 05 December, 2006.
1085
1086This used Opera 11.0, and `html_to_quickbook.css` as a special display format.
1087On the Opera full taskbar (chose ['enable full taskbar]) View, Style, Manage modes, Display.
1088
1089Choose ['add `\boost-sandbox\boost_docs\trunk\doc\style\html\conversion\html_to_quickbook.css`]
1090to My Style Sheet.  Html pages are now displayed as Quickbook and can be copied and pasted
1091into quickbook files using your favored text editor for Quickbook.
1092
1093[h4 Version 1.0.0, January 1, 2000]
1094
1095['First release]
1096
1097[endsect] [/section:history Appendix A: History]
1098
1099[section:faq Appendix B: FAQ]
1100
1101[h5 Why should I use Pool?]
1102
1103Using Pools gives you more control over how memory is used in your program.
1104For example, you could have a situation where you want to allocate a
1105bunch of small objects at one point, and then reach a point in your program
1106where none of them are needed any more. Using pool interfaces,
1107you can choose to run their destructors or just drop them off into oblivion;
1108the pool interface will guarantee that there are no system memory leaks.
1109
1110[h5 When should I use Pool?]
1111
1112Pools are generally used when there is a lot of allocation and deallocation of small objects.
1113Another common usage is the situation above, where many objects may be dropped out of memory.
1114
1115In general, use Pools when you need a more efficient way to do unusual memory control.
1116
1117[endsect] [/section:faq Appendix B: FAQ]
1118
1119[section:acknowledgements Appendix C: Acknowledgements]
1120
1121Many, many thanks to the Boost peers, notably Jeff Garland, Beman Dawes, Ed Brey,
1122Gary Powell, Peter Dimov, and Jens Maurer for providing helpful suggestions!
1123
1124[endsect] [/section:acknowledgements Appendix C: Acknowledgements]
1125
1126[section:tests  Appendix D: Tests]
1127
1128See folder `boost/libs/pool/test/`.
1129
1130[endsect] [/section:tests  Appendix D: Tests]
1131
1132[section:tickets  Appendix E: Tickets]
1133
1134Report and view bugs and features by adding a ticket at [@https://svn.boost.org/trac/boost Boost.Trac].
1135
1136Existing open tickets for this library alone can be viewed
1137[@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=pool&col=id&col=summary&col=status&col=owner&col=type&col=milestone&order=priority here].
1138Existing tickets for this library - including closed ones - can be viewed
1139[@https://svn.boost.org/trac/boost/query?status=assigned&status=closed&status=new&status=reopened&component=pool&col=id&col=summary&col=status&col=owner&col=type&col=milestone&order=priority here].
1140
1141[endsect] [/section:tickets  Appendix E: Tickets]
1142
1143[section:implementations  Appendix F: Other Implementations]
1144
1145Pool allocators are found in many programming languages, and in many variations.
1146The beginnings of many implementations may be found in common programming literature;
1147some of these are given below. Note that none of these are complete implementations of a Pool;
1148most of these leave some aspects of a Pool as a user exercise. However, in each case,
1149even though some aspects are missing, these examples use the same underlying concept
1150of a Simple Segregated Storage described in this document.
1151
1152# ['The C++ Programming Language], 3rd ed., by Bjarne Stroustrup, Section 19.4.2. Missing aspects:
1153  * Not portable.
1154  * Cannot handle allocations of arbitrary numbers of objects (this was left as an exercise).
1155  * Not thread-safe.
1156  * Suffers from the static initialization problem.
1157# ['MicroC/OS-II: The Real-Time Kernel], by Jean J. Labrosse, Chapter 7 and Appendix B.04.
1158  * An example of the Simple Segregated Storage scheme at work in the internals of an actual OS.
1159  * Missing aspects:
1160  * Not portable (though this is OK, since it's part of its own OS).
1161  * Cannot handle allocations of arbitrary numbers of blocks (which is also OK, since this feature is not needed).
1162  * Requires non-intuitive user code to create and destroy the Pool.
1163# ['Efficient C++: Performance Programming Techniques], by Dov Bulka and David Mayhew, Chapters 6 and 7.
1164  * This is a good example of iteratively developing a Pool solutio.
1165  * however, their premise (that the system-supplied allocation mechanism is hopelessly inefficient) is flawed on every system I've tested on.
1166  * Run their timings on your system before you accept their conclusions.
1167  * Missing aspect: Requires non-intuitive user code to create and destroy the Pool.
1168# ['Advanced C++: Programming Styles and Idioms], by James O. Coplien, Section 3.6.
1169  * Has examples of both static and dynamic pooling, but missing aspects:
1170  * Not thread-safe.
1171  * The static pooling example is not portable.
1172
1173[endsect] [/section:implementations  Appendix F: Other Implementations]
1174
1175[section:references  Appendix G: References]
1176
1177# [#ref1] Doug Lea, A Memory Allocator. See [@http://gee.cs.oswego.edu/dl/html/malloc.html http://gee.cs.oswego.edu/dl/html/malloc.html]
1178# [#ref2]Paul R. Wilson, Mark S. Johnstone, Michael Neely, and David Boles,
1179['Dynamic Storage Allocation: A Survey and Critical Review]
1180in International Workshop on Memory Management, September 1995, pg. 28, 36.
1181See [@ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps]
1182
1183[endsect] [/section:references  Appendix G: references]
1184
1185[section:todo  Appendix H: Future plans]
1186
1187Another pool interface will be written: a base class for per-class pool allocation.
1188
1189This "pool_base" interface will be Singleton Usage with Exceptions,
1190and built on the singleton_pool interface.
1191
1192[endsect] [/section:todo  Appendix G: Future plans]
1193
1194[endsect] [/section:appendices Appendices]
1195
1196[section:indexes Indexes]
1197
1198[include auto_index_helpers.qbk]
1199
1200[named_index function_name Function Index]
1201[named_index class_name Class Index]
1202[named_index typedef_name Typedef Index]
1203[index]
1204
1205[endsect] [/section:indexes Indexes]
1206