]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/flyweight/doc/tutorial/technical.html
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / flyweight / doc / tutorial / technical.html
CommitLineData
7c673cae
FG
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&lt;T&gt;</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&lt;T&gt;</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&lt;T&gt;</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>&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>
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&lt;std::string&gt;</span>
76 <span class=special>}</span>
77 <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>
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&lt;std::string&gt;</code>.
90Static data initialization can potentially be executed twice concurrently
91if two threads happen to collide on the first usage of
92<code>flyweight&lt;std::string&gt;</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>&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>
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>&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>
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&lt;T&gt;::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>&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>
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&lt;std::string&gt;</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&lt;std::string&gt;</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&lt;std::string&gt;</code> before <code>v</code> is
158created. Here, calling
159the function <code>flyweight&lt;std::string&gt;::init</code> is a little
160cumbersome, so we can resort to the utility type
161<code>flyweight&lt;std::string&gt;::initializer</code> to do that job for us:
162</p>
163
164<blockquote><pre>
165<span class=comment>// equivalent to calling flyweight&lt;std::string&gt;::init()</span>
166<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>
167<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>
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>&copy; Copyright 2006-2010 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>