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> 19Extending 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> 22Boost.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> 25Annex: 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> 39For any given <code>T</code>, the type <code>flyweight<T></code> 40maintains some class-wide or static data that needs to be properly 41initialized before the class can be used. The internal machinery of 42Boost.Flyweight guarantees that static data initialization 43takes place automatically before the first use of the particular 44<code>flyweight<T></code> instantiation in the program, and in 45any case always during the so-called <i>dynamic initialization phase</i> 46of the program startup sequence. Although this is not strictly 47required by the C++ standard, in current practice dynamic initialization 48is completed before <code>main()</code> begins. 49</p> 50 51<p> 52So, for all practical purposes, static data initialization is performed 53before <code>main()</code> or before the first pre-<code>main()</code> 54usage of the class, for instance if we declare a global 55<code>static flyweight<T></code> object. This covers the vast 56majority of usage cases in a transparent manner, but there are 57some scenarios where the automatic static data initialization 58policy 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> 88The global pool of the example launches several threads, each of which 89internally uses <code>flyweight<std::string></code>. 90Static data initialization can potentially be executed twice concurrently 91if two threads happen to collide on the first usage of 92<code>flyweight<std::string></code>: Boost.Flyweight initialization 93does not consider thread safety. So, we need to explicitly take care of 94static data initialization in a thread safe context before launching 95the 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> 111The static member function <code>init</code> is not thread safe, either: in our particular 112example it just happens to be called in a single threaded environment. 113When concurrency can happen, <code>flyweight<T>::init</code> must 114be properly synchronized by the programmer by using some mutual exclusion 115mechanisms of her own. 116</p> 117 118<p> 119The following is another example where the default static initialization 120provided 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> 133In some environments, the program above fails when exiting. For instance, if run 134from Microsoft Visual C++ environment in debug mode, a breakpoint is triggered 135at termination time and the debug output window shows a message along the following: 136</p> 137 138<blockquote><pre> 139HEAP[test.exe]: HEAP: Free Heap block 3a6488 modified at 3a6650 after it was 140freed 141Windows has triggered a breakpoint in test.exe. 142This may be due to a corruption of the heap, and indicates a bug in test.exe 143or any of the DLLs it has loaded. 144The output window may have more diagnostic information 145</pre></blockquote> 146 147<p> 148What 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 150need not create any flyweight object proper; so, 151it is perfectly possible that the static initialization of 152<code>flyweight<std::string></code> happens <i>after</i> the construction 153of <code>v</code>; when this is the case, the static destruction of 154the associated factory will occur <i>before</i> <code>v</code>'s 155destruction, leaving the vector with dangling flyweights. 156Again, the solution consists in explicitly forcing the static instantiation 157of <code>flyweight<std::string></code> before <code>v</code> is 158created. Here, calling 159the function <code>flyweight<std::string>::init</code> is a little 160cumbersome, 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> 178Extending 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> 181Boost.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> 184Annex: 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. 192Distributed under the Boost Software 193License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> 194LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> 195http://www.boost.org/LICENSE_1_0.txt</a>) 196</p> 197 198</body> 199</html> 200