]>
Commit | Line | Data |
---|---|---|
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN"> | |
2 | ||
3 | <html> | |
4 | <head> | |
5 | <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> | |
6 | <title>Boost.Flyweight Documentation - Tutorial - Technical issues</title> | |
7 | <link rel="stylesheet" href="../style.css" type="text/css"> | |
8 | <link rel="start" href="../index.html"> | |
9 | <link rel="prev" href="extension.html"> | |
10 | <link rel="up" href="index.html"> | |
11 | <link rel="next" href="lambda_expressions.html"> | |
12 | </head> | |
13 | ||
14 | <body> | |
15 | <h1><img src="../../../../boost.png" alt="Boost logo" align= | |
16 | "middle" width="277" height="86">Boost.Flyweight Tutorial: Technical issues</h1> | |
17 | ||
18 | <div class="prev_link"><a href="extension.html"><img src="../prev.gif" alt="extending Boost.Flyweight" border="0"><br> | |
19 | Extending Boost.Flyweight | |
20 | </a></div> | |
21 | <div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br> | |
22 | Boost.Flyweight tutorial | |
23 | </a></div> | |
24 | <div class="next_link"><a href="lambda_expressions.html"><img src="../next.gif" alt="annex: MPL lambda expressions" border="0"><br> | |
25 | Annex: MPL lambda expressions | |
26 | </a></div><br clear="all" style="clear: all;"> | |
27 | ||
28 | <hr> | |
29 | ||
30 | <h2>Contents</h2> | |
31 | ||
32 | <ul> | |
33 | <li><a href="#static_init">Static data initialization</a></li> | |
34 | </ul> | |
35 | ||
36 | <h2><a name="static_init">Static data initialization</a></h2> | |
37 | ||
38 | <p> | |
39 | For any given <code>T</code>, the type <code>flyweight<T></code> | |
40 | maintains some class-wide or static data that needs to be properly | |
41 | initialized before the class can be used. The internal machinery of | |
42 | Boost.Flyweight guarantees that static data initialization | |
43 | takes place automatically before the first use of the particular | |
44 | <code>flyweight<T></code> instantiation in the program, and in | |
45 | any case always during the so-called <i>dynamic initialization phase</i> | |
46 | of the program startup sequence. Although this is not strictly | |
47 | required by the C++ standard, in current practice dynamic initialization | |
48 | is completed before <code>main()</code> begins. | |
49 | </p> | |
50 | ||
51 | <p> | |
52 | So, for all practical purposes, static data initialization is performed | |
53 | before <code>main()</code> or before the first pre-<code>main()</code> | |
54 | usage of the class, for instance if we declare a global | |
55 | <code>static flyweight<T></code> object. This covers the vast | |
56 | majority of usage cases in a transparent manner, but there are | |
57 | some scenarios where the automatic static data initialization | |
58 | policy of Boost.Flyweight can fail: | |
59 | </p> | |
60 | ||
61 | <blockquote><pre> | |
62 | <span class=comment>// global thread pool</span> | |
63 | ||
64 | <span class=keyword>class</span> <span class=identifier>thread_pool</span> | |
65 | <span class=special>{</span> | |
66 | <span class=keyword>public</span><span class=special>:</span> | |
67 | <span class=identifier>thread_pool</span><span class=special>()</span> | |
68 | <span class=special>{</span> | |
69 | <span class=keyword>for</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>i</span><span class=special>=</span><span class=number>0</span><span class=special>;</span><span class=identifier>i</span><span class=special><</span><span class=number>100</span><span class=special>;++</span><span class=identifier>i</span><span class=special>)</span><span class=identifier>p</span><span class=special>[</span><span class=identifier>i</span><span class=special>]=</span><span class=identifier>shared_ptr</span><span class=special><</span><span class=identifier>thread</span><span class=special>>(</span><span class=keyword>new</span> <span class=identifier>thread</span><span class=special>(</span><span class=identifier>thread_fun</span><span class=special>));</span> | |
70 | <span class=special>}</span> | |
71 | ||
72 | <span class=keyword>private</span><span class=special>:</span> | |
73 | <span class=keyword>static</span> <span class=keyword>void</span> <span class=identifier>thread_fun</span><span class=special>()</span> | |
74 | <span class=special>{</span> | |
75 | <span class=comment>// uses flyweight<std::string></span> | |
76 | <span class=special>}</span> | |
77 | <span class=identifier>array</span><span class=special><</span><span class=identifier>shared_ptr</span><span class=special><</span><span class=identifier>thread</span><span class=special>>,</span><span class=number>100</span><span class=special>></span> <span class=identifier>p</span><span class=special>;</span> | |
78 | <span class=special>};</span> | |
79 | ||
80 | <span class=keyword>static</span> <span class=identifier>thread_pool</span> <span class=identifier>thpool</span><span class=special>;</span> | |
81 | ||
82 | <span class=keyword>int</span> <span class=identifier>main</span><span class=special>()</span> | |
83 | <span class=special>{</span> | |
84 | <span class=special>...</span> | |
85 | </pre></blockquote> | |
86 | ||
87 | <p> | |
88 | The global pool of the example launches several threads, each of which | |
89 | internally uses <code>flyweight<std::string></code>. | |
90 | Static data initialization can potentially be executed twice concurrently | |
91 | if two threads happen to collide on the first usage of | |
92 | <code>flyweight<std::string></code>: Boost.Flyweight initialization | |
93 | does not consider thread safety. So, we need to explicitly take care of | |
94 | static data initialization in a thread safe context before launching | |
95 | the threads: | |
96 | </p> | |
97 | ||
98 | <blockquote><pre> | |
99 | <span class=keyword>class</span> <span class=identifier>thread_pool</span> | |
100 | <span class=special>{</span> | |
101 | <span class=keyword>public</span><span class=special>:</span> | |
102 | <span class=identifier>thread_pool</span><span class=special>()</span> | |
103 | <span class=special>{</span> | |
104 | <b><span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>::</span><span class=identifier>init</span><span class=special>();</span></b> | |
105 | <span class=keyword>for</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>i</span><span class=special>=</span><span class=number>0</span><span class=special>;</span><span class=identifier>i</span><span class=special><</span><span class=number>100</span><span class=special>;++</span><span class=identifier>i</span><span class=special>)</span><span class=identifier>p</span><span class=special>[</span><span class=identifier>i</span><span class=special>]=</span><span class=identifier>shared_ptr</span><span class=special><</span><span class=identifier>thread</span><span class=special>>(</span><span class=keyword>new</span> <span class=identifier>thread</span><span class=special>(</span><span class=identifier>thread_fun</span><span class=special>));</span> | |
106 | <span class=special>}</span> | |
107 | <span class=special>...</span> | |
108 | </pre></blockquote> | |
109 | ||
110 | <p> | |
111 | The static member function <code>init</code> is not thread safe, either: in our particular | |
112 | example it just happens to be called in a single threaded environment. | |
113 | When concurrency can happen, <code>flyweight<T>::init</code> must | |
114 | be properly synchronized by the programmer by using some mutual exclusion | |
115 | mechanisms of her own. | |
116 | </p> | |
117 | ||
118 | <p> | |
119 | The following is another example where the default static initialization | |
120 | provided by Boost.Flyweight can fail: | |
121 | </p> | |
122 | ||
123 | <blockquote><pre> | |
124 | <span class=keyword>static</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special><</span><span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=special>></span> <span class=identifier>v</span><span class=special>;</span> | |
125 | ||
126 | <span class=keyword>int</span> <span class=identifier>main</span><span class=special>()</span> | |
127 | <span class=special>{</span> | |
128 | <span class=comment>// use v</span> | |
129 | <span class=special>}</span> | |
130 | </pre></blockquote> | |
131 | ||
132 | <p> | |
133 | In some environments, the program above fails when exiting. For instance, if run | |
134 | from Microsoft Visual C++ environment in debug mode, a breakpoint is triggered | |
135 | at termination time and the debug output window shows a message along the following: | |
136 | </p> | |
137 | ||
138 | <blockquote><pre> | |
139 | HEAP[test.exe]: HEAP: Free Heap block 3a6488 modified at 3a6650 after it was | |
140 | freed | |
141 | Windows has triggered a breakpoint in test.exe. | |
142 | This may be due to a corruption of the heap, and indicates a bug in test.exe | |
143 | or any of the DLLs it has loaded. | |
144 | The output window may have more diagnostic information | |
145 | </pre></blockquote> | |
146 | ||
147 | <p> | |
148 | What is the problem? Although the type of <code>v</code> involves | |
149 | <code>flyweight<std::string></code>, constructing <code>v</code> as an empty vector | |
150 | need not create any flyweight object proper; so, | |
151 | it is perfectly possible that the static initialization of | |
152 | <code>flyweight<std::string></code> happens <i>after</i> the construction | |
153 | of <code>v</code>; when this is the case, the static destruction of | |
154 | the associated factory will occur <i>before</i> <code>v</code>'s | |
155 | destruction, leaving the vector with dangling flyweights. | |
156 | Again, the solution consists in explicitly forcing the static instantiation | |
157 | of <code>flyweight<std::string></code> before <code>v</code> is | |
158 | created. Here, calling | |
159 | the function <code>flyweight<std::string>::init</code> is a little | |
160 | cumbersome, so we can resort to the utility type | |
161 | <code>flyweight<std::string>::initializer</code> to do that job for us: | |
162 | </p> | |
163 | ||
164 | <blockquote><pre> | |
165 | <span class=comment>// equivalent to calling flyweight<std::string>::init()</span> | |
166 | <b><span class=keyword>static</span> <span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>::</span><span class=identifier>initializer</span> <span class=identifier>fwinit</span><span class=special>;</span></b> | |
167 | <span class=keyword>static</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special><</span><span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=special>></span> <span class=identifier>v</span><span class=special>;</span> | |
168 | ||
169 | <span class=keyword>int</span> <span class=identifier>main</span><span class=special>()</span> | |
170 | <span class=special>{</span> | |
171 | <span class=comment>// use v; no dangling flyweights at termination now</span> | |
172 | <span class=special>}</span> | |
173 | </pre></blockquote> | |
174 | ||
175 | <hr> | |
176 | ||
177 | <div class="prev_link"><a href="extension.html"><img src="../prev.gif" alt="extending Boost.Flyweight" border="0"><br> | |
178 | Extending Boost.Flyweight | |
179 | </a></div> | |
180 | <div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br> | |
181 | Boost.Flyweight tutorial | |
182 | </a></div> | |
183 | <div class="next_link"><a href="lambda_expressions.html"><img src="../next.gif" alt="annex: MPL lambda expressions" border="0"><br> | |
184 | Annex: MPL lambda expressions | |
185 | </a></div><br clear="all" style="clear: all;"> | |
186 | ||
187 | <br> | |
188 | ||
189 | <p>Revised Octber 16th 2010</p> | |
190 | ||
191 | <p>© Copyright 2006-2010 Joaquín M López Muñoz. | |
192 | Distributed under the Boost Software | |
193 | License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> | |
194 | LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> | |
195 | http://www.boost.org/LICENSE_1_0.txt</a>) | |
196 | </p> | |
197 | ||
198 | </body> | |
199 | </html> |