technical.html 11 KB

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