]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libstdc++-v3/contrib/libstdc++-v3-4.7/doc/html/manual/bk01pt03ch20s03.html
update
[l4.git] / l4 / pkg / libstdc++-v3 / contrib / libstdc++-v3-4.7 / doc / html / manual / bk01pt03ch20s03.html
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml"><head><title>Implementation</title><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"/><meta name="keywords" content="&#10;      ISO C++&#10;    , &#10;      allocator&#10;    "/><meta name="keywords" content="&#10;      ISO C++&#10;    , &#10;      library&#10;    "/><meta name="keywords" content="&#10;      ISO C++&#10;    , &#10;      runtime&#10;    , &#10;      library&#10;    "/><link rel="home" href="../index.html" title="The GNU C++ Library"/><link rel="up" href="mt_allocator.html" title="Chapter 20. The mt_allocator"/><link rel="prev" href="bk01pt03ch20s02.html" title="Design Issues"/><link rel="next" href="bk01pt03ch20s04.html" title="Single Thread Example"/></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Implementation</th></tr><tr><td align="left"><a accesskey="p" href="bk01pt03ch20s02.html">Prev</a> </td><th width="60%" align="center">Chapter 20. The mt_allocator</th><td align="right"> <a accesskey="n" href="bk01pt03ch20s04.html">Next</a></td></tr></table><hr/></div><div class="section" title="Implementation"><div class="titlepage"><div><div><h2 class="title"><a id="allocator.mt.impl"/>Implementation</h2></div></div></div><div class="section" title="Tunable Parameters"><div class="titlepage"><div><div><h3 class="title"><a id="allocator.mt.tune"/>Tunable Parameters</h3></div></div></div><p>Certain allocation parameters can be modified, or tuned. There
4 exists a nested <code class="code">struct __pool_base::_Tune</code> that contains all
5 these parameters, which include settings for
6 </p><div class="itemizedlist"><ul class="itemizedlist"><li class="listitem"><p>Alignment</p></li><li class="listitem"><p>Maximum bytes before calling <code class="code">::operator new</code> directly</p></li><li class="listitem"><p>Minimum bytes</p></li><li class="listitem"><p>Size of underlying global allocations</p></li><li class="listitem"><p>Maximum number of supported threads</p></li><li class="listitem"><p>Migration of deallocations to the global free list</p></li><li class="listitem"><p>Shunt for global <code class="code">new</code> and <code class="code">delete</code></p></li></ul></div><p>Adjusting parameters for a given instance of an allocator can only
7 happen before any allocations take place, when the allocator itself is
8 initialized. For instance:
9 </p><pre class="programlisting">
10 #include &lt;ext/mt_allocator.h&gt;
11
12 struct pod
13 {
14   int i;
15   int j;
16 };
17
18 int main()
19 {
20   typedef pod value_type;
21   typedef __gnu_cxx::__mt_alloc&lt;value_type&gt; allocator_type;
22   typedef __gnu_cxx::__pool_base::_Tune tune_type;
23
24   tune_type t_default;
25   tune_type t_opt(16, 5120, 32, 5120, 20, 10, false);
26   tune_type t_single(16, 5120, 32, 5120, 1, 10, false);
27
28   tune_type t;
29   t = allocator_type::_M_get_options();
30   allocator_type::_M_set_options(t_opt);
31   t = allocator_type::_M_get_options();
32
33   allocator_type a;
34   allocator_type::pointer p1 = a.allocate(128);
35   allocator_type::pointer p2 = a.allocate(5128);
36
37   a.deallocate(p1, 128);
38   a.deallocate(p2, 5128);
39
40   return 0;
41 }
42 </pre></div><div class="section" title="Initialization"><div class="titlepage"><div><div><h3 class="title"><a id="allocator.mt.init"/>Initialization</h3></div></div></div><p>
43 The static variables (pointers to freelists, tuning parameters etc)
44 are initialized as above, or are set to the global defaults.
45 </p><p>
46 The very first allocate() call will always call the
47 _S_initialize_once() function.  In order to make sure that this
48 function is called exactly once we make use of a __gthread_once call
49 in MT applications and check a static bool (_S_init) in ST
50 applications.
51 </p><p>
52 The _S_initialize() function:
53 - If the GLIBCXX_FORCE_NEW environment variable is set, it sets the bool
54   _S_force_new to true and then returns. This will cause subsequent calls to
55   allocate() to return memory directly from a new() call, and deallocate will
56   only do a delete() call.
57 </p><p>
58 - If the GLIBCXX_FORCE_NEW environment variable is not set, both ST and MT
59   applications will:
60   - Calculate the number of bins needed. A bin is a specific power of two size
61     of bytes. I.e., by default the allocator will deal with requests of up to
62     128 bytes (or whatever the value of _S_max_bytes is when _S_init() is
63     called). This means that there will be bins of the following sizes
64     (in bytes): 1, 2, 4, 8, 16, 32, 64, 128.
65
66   - Create the _S_binmap array. All requests are rounded up to the next
67     "large enough" bin. I.e., a request for 29 bytes will cause a block from
68     the "32 byte bin" to be returned to the application. The purpose of
69     _S_binmap is to speed up the process of finding out which bin to use.
70     I.e., the value of _S_binmap[ 29 ] is initialized to 5 (bin 5 = 32 bytes).
71 </p><p>
72   - Create the _S_bin array. This array consists of bin_records. There will be
73     as many bin_records in this array as the number of bins that we calculated
74     earlier. I.e., if _S_max_bytes = 128 there will be 8 entries.
75     Each bin_record is then initialized:
76     - bin_record-&gt;first = An array of pointers to block_records. There will be
77       as many block_records pointers as there are maximum number of threads
78       (in a ST application there is only 1 thread, in a MT application there
79       are _S_max_threads).
80       This holds the pointer to the first free block for each thread in this
81       bin. I.e., if we would like to know where the first free block of size 32
82       for thread number 3 is we would look this up by: _S_bin[ 5 ].first[ 3 ]
83
84     The above created block_record pointers members are now initialized to
85     their initial values. I.e. _S_bin[ n ].first[ n ] = NULL;
86 </p><p>
87 - Additionally a MT application will:
88   - Create a list of free thread id's. The pointer to the first entry
89     is stored in _S_thread_freelist_first. The reason for this approach is
90     that the __gthread_self() call will not return a value that corresponds to
91     the maximum number of threads allowed but rather a process id number or
92     something else. So what we do is that we create a list of thread_records.
93     This list is _S_max_threads long and each entry holds a size_t thread_id
94     which is initialized to 1, 2, 3, 4, 5 and so on up to _S_max_threads.
95     Each time a thread calls allocate() or deallocate() we call
96     _S_get_thread_id() which looks at the value of _S_thread_key which is a
97     thread local storage pointer. If this is NULL we know that this is a newly
98     created thread and we pop the first entry from this list and saves the
99     pointer to this record in the _S_thread_key variable. The next time
100     we will get the pointer to the thread_record back and we use the
101     thread_record-&gt;thread_id as identification. I.e., the first thread that
102     calls allocate will get the first record in this list and thus be thread
103     number 1 and will then find the pointer to its first free 32 byte block
104     in _S_bin[ 5 ].first[ 1 ]
105     When we create the _S_thread_key we also define a destructor
106     (_S_thread_key_destr) which means that when the thread dies, this
107     thread_record is returned to the front of this list and the thread id
108     can then be reused if a new thread is created.
109     This list is protected by a mutex (_S_thread_freelist_mutex) which is only
110     locked when records are removed or added to the list.
111 </p><p>
112   - Initialize the free and used counters of each bin_record:
113     - bin_record-&gt;free = An array of size_t. This keeps track of the number
114       of blocks on a specific thread's freelist in each bin. I.e., if a thread
115       has 12 32-byte blocks on it's freelists and allocates one of these, this
116       counter would be decreased to 11.
117
118     - bin_record-&gt;used = An array of size_t. This keeps track of the number
119       of blocks currently in use of this size by this thread. I.e., if a thread
120       has made 678 requests (and no deallocations...) of 32-byte blocks this
121       counter will read 678.
122
123     The above created arrays are now initialized with their initial values.
124     I.e. _S_bin[ n ].free[ n ] = 0;
125 </p><p>
126   - Initialize the mutex of each bin_record: The bin_record-&gt;mutex
127     is used to protect the global freelist. This concept of a global
128     freelist is explained in more detail in the section "A multi
129     threaded example", but basically this mutex is locked whenever a
130     block of memory is retrieved or returned to the global freelist
131     for this specific bin. This only occurs when a number of blocks
132     are grabbed from the global list to a thread specific list or when
133     a thread decides to return some blocks to the global freelist.
134 </p></div><div class="section" title="Deallocation Notes"><div class="titlepage"><div><div><h3 class="title"><a id="allocator.mt.deallocation"/>Deallocation Notes</h3></div></div></div><p> Notes about deallocation. This allocator does not explicitly
135 release memory. Because of this, memory debugging programs like
136 valgrind or purify may notice leaks: sorry about this
137 inconvenience. Operating systems will reclaim allocated memory at
138 program termination anyway. If sidestepping this kind of noise is
139 desired, there are three options: use an allocator, like
140 <code class="code">new_allocator</code> that releases memory while debugging, use
141 GLIBCXX_FORCE_NEW to bypass the allocator's internal pools, or use a
142 custom pool datum that releases resources on destruction.
143 </p><p>
144   On systems with the function <code class="code">__cxa_atexit</code>, the
145 allocator can be forced to free all memory allocated before program
146 termination with the member function
147 <code class="code">__pool_type::_M_destroy</code>. However, because this member
148 function relies on the precise and exactly-conforming ordering of
149 static destructors, including those of a static local
150 <code class="code">__pool</code> object, it should not be used, ever, on systems
151 that don't have the necessary underlying support. In addition, in
152 practice, forcing deallocation can be tricky, as it requires the
153 <code class="code">__pool</code> object to be fully-constructed before the object
154 that uses it is fully constructed. For most (but not all) STL
155 containers, this works, as an instance of the allocator is constructed
156 as part of a container's constructor. However, this assumption is
157 implementation-specific, and subject to change. For an example of a
158 pool that frees memory, see the following
159     <a class="link" href="http://gcc.gnu.org/viewcvs/trunk/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-6.cc?view=markup">
160     example.</a>
161 </p></div></div><div class="navfooter"><hr/><table width="100%" summary="Navigation footer"><tr><td align="left"><a accesskey="p" href="bk01pt03ch20s02.html">Prev</a> </td><td align="center"><a accesskey="u" href="mt_allocator.html">Up</a></td><td align="right"> <a accesskey="n" href="bk01pt03ch20s04.html">Next</a></td></tr><tr><td align="left" valign="top">Design Issues </td><td align="center"><a accesskey="h" href="../index.html">Home</a></td><td align="right" valign="top"> Single Thread Example</td></tr></table></div></body></html>