1 <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0.1 Transitional//EN">
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">
15 <h1><img src=
"../../../../boost.png" alt=
"Boost logo" align=
16 "middle" width=
"277" height=
"86">Boost.Flyweight Tutorial: Technical issues
</h1>
18 <div class=
"prev_link"><a href=
"extension.html"><img src=
"../prev.gif" alt=
"extending Boost.Flyweight" border=
"0"><br>
19 Extending Boost.Flyweight
21 <div class=
"up_link"><a href=
"index.html"><img src=
"../up.gif" alt=
"Boost.Flyweight tutorial" border=
"0"><br>
22 Boost.Flyweight tutorial
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;">
33 <li><a href=
"#static_init">Static data initialization
</a></li>
36 <h2><a name=
"static_init">Static data initialization
</a></h2>
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.
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:
62 <span class=comment
>// global thread pool
</span>
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>
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>
80 <span class=keyword
>static
</span> <span class=identifier
>thread_pool
</span> <span class=identifier
>thpool
</span><span class=special
>;
</span>
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>
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
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>
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.
119 The following is another example where the default static initialization
120 provided by Boost.Flyweight can fail:
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>
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>
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:
139 HEAP[test.exe]: HEAP: Free Heap block
3a6488 modified at
3a6650 after it was
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
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:
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>
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>
177 <div class=
"prev_link"><a href=
"extension.html"><img src=
"../prev.gif" alt=
"extending Boost.Flyweight" border=
"0"><br>
178 Extending Boost.Flyweight
180 <div class=
"up_link"><a href=
"index.html"><img src=
"../up.gif" alt=
"Boost.Flyweight tutorial" border=
"0"><br>
181 Boost.Flyweight tutorial
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;">
189 <p>Revised Octber
16th
2010</p>
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>)