]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/flyweight/doc/tutorial/configuration.html
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / flyweight / doc / tutorial / configuration.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 - Configuring Boost.Flyweight</title>
7<link rel="stylesheet" href="../style.css" type="text/css">
8<link rel="start" href="../index.html">
9<link rel="prev" href="key_value.html">
10<link rel="up" href="index.html">
11<link rel="next" href="extension.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: Configuring Boost.Flyweight</h1>
17
18<div class="prev_link"><a href="key_value.html"><img src="../prev.gif" alt="key-value flyweights" border="0"><br>
19Key-value flyweights
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="extension.html"><img src="../next.gif" alt="extending Boost.Flyweight" border="0"><br>
25Extending Boost.Flyweight
26</a></div><br clear="all" style="clear: all;">
27
28<hr>
29
30<h2>Contents</h2>
31
32<ul>
33 <li><a href="#intro">Configurable aspects of Boost.Flyweight</a>
34 <ul>
35 <li><a href="#free_order_template">Free-order template parameter interface</a></li>
36 <li><a href="#header_inclusion">Header inclusion</a></li>
37 </ul>
38 </li>
39 <li><a href="#tagging">Tagging</a></li>
40 <li><a href="#factories">Factory specification</a>
41 <ul>
42 <li><a href="#factory_types">Types involved in the configuration of factories</a></li>
43 <li><a href="#hashed_factory"><code>hashed_factory</code></a></li>
44 <li><a href="#set_factory"><code>set_factory</code></a></li>
45 <li><a href="#assoc_container_factory"><code>assoc_container_factory</code></a></li>
46 </ul>
47 </li>
48 <li><a href="#holders">Holder specification</a>
49 <ul>
50 <li><a href="#static_holder"><code>static_holder</code></a></li>
51 <li><a href="#intermodule_holder"><code>intermodule_holder</code></a></li>
52 </ul>
53 </li>
54 <li><a href="#locking">Locking policies</a>
55 <ul>
56 <li><a href="#simple_locking"><code>simple_locking</code></a></li>
57 <li><a href="#no_locking"><code>no_locking</code></a></li>
58 </ul>
59 </li>
60 <li><a href="#tracking">Tracking policies</a>
61 <ul>
62 <li><a href="#refcounted"><code>refcounted</code></a></li>
63 <li><a href="#no_tracking"><code>no_tracking</code></a></li>
64 </ul>
65 </li>
66</ul>
67
68<h2><a name="intro">Configurable aspects of Boost.Flyweight</a></h2>
69
70<p>
71Most of the time, <code>flyweight</code> default configuration is just good
72enough and the user need not care about further tuning of her <code>flyweight</code>
73instantiations; however, when the necessity for more control over Boost.Flyweight
74behavior arises, comprehensive mechanisms are provided to select, configure and
75even extend the following implementation aspects:
76<ul>
77 <li><a href="#tagging">Type tagging</a>.</li>
78 <li><a href="#factories">Factory</a> used to store the shared values
79 <code>flyweight</code> objects refer to.
80 </li>
81 <li><a href="#holders">Mechanism of instantiation</a> of the flyweight factory.</li>
82 <li>Internal <a href="#locking">synchronization mechanism</a> for access to
83 the internal factory in multithreaded environments.</li>
84 <li><a href="#tracking">Tracking policy</a> controlling how a value stored in the
85 factory is handled when all the flyweight objects associated to it are
86 destroyed.
87 </li>
88</ul>
89</p>
90
91<h3><a name="free_order_template">Free-order template parameter interface</a></h3>
92
93<p>
94The <code>flyweight</code> class template features a "smart" specification
95interface by which the configuration aspects can be provided as optional template arguments
96in whatever order the user pleases. For instance, a tagged <code>flyweight</code>
97of <code>std::string</code>s with a <a href="#set_factory">set-based factory</a> and
98<a href="#no_tracking">no tracking</a> can be specified like this:
99</p>
100
101<blockquote><pre>
102<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>,</span> <span class=identifier>tag</span><span class=special>&lt;</span><span class=identifier>label_t</span><span class=special>&gt;,</span> <span class=identifier>set_factory</span><span class=special>&lt;&gt;,</span> <span class=identifier>no_tracking</span> <span class=special>&gt;</span>
103</pre></blockquote>
104
105<p>
106or like this:
107</p>
108
109<blockquote><pre>
110<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>,</span> <span class=identifier>no_tracking</span><span class=special>,</span> <span class=identifier>tag</span><span class=special>&lt;</span><span class=identifier>label_t</span><span class=special>&gt;,</span> <span class=identifier>set_factory</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
111</pre></blockquote>
112
113<p>
114or in any other order; only <code>std::string</code> is required to occupy
115the first place in the specification.
116</p>
117
118<h3><a name="header_inclusion">Header inclusion</a></h3>
119
120<p>
121The example code shown at the <a href="basics.html#intro">introductory section</a>
122uses the
123<a href="../reference/index.html#flyweight_synopsis"><code>"boost/flyweight.hpp"</code></a>
124convenience header, which simply includes the headers for the class template
125<code>flyweight</code> and its default configuration components:
126</p>
127
128<blockquote><pre>
129<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span> <span class=comment>// class template flyweight</span>
130<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>hashed_factory</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span> <span class=comment>// hashed flyweight factory</span>
131<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>static_holder</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span> <span class=comment>// regular factory instantiation</span>
132<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>simple_locking</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span> <span class=comment>// simple locking policy</span>
133<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>refcounted</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span> <span class=comment>// refcounting tracking policy</span>
134</pre></blockquote>
135
136<p>
137When using components other than these, their specific headers must be
138explicitly included.
139</p>
140
141<h2><a name="tagging">Tagging</a></h2>
142
143<p>
144Consider the following two types:
145</p>
146
147<blockquote><pre>
148<span class=keyword>typedef</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>name_t</span><span class=special>;</span>
149<span class=keyword>typedef</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>ip_address_t</span><span class=special>;</span>
150</pre></blockquote>
151
152<p>
153Although technically both types are identical, this is so by virtue of
154coincidence, as there is no sensible relation between names and IP addresses.
155Internally, the fact that <code>name_t</code> and <code>ip_address_t</code>
156are the same flyweight type causes values of both classes to be stored together
157in the same flyweight factory, although their respective ranges
158are not expected to overlap. <i>Tagging</i> can be used to turn these
159into really different types:
160</p>
161
162<blockquote><pre>
163<span class=keyword>struct</span> <span class=identifier>name_tag</span><span class=special>{};</span>
164<span class=keyword>typedef</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>,</span><span class=identifier>tag</span><span class=special>&lt;</span><span class=identifier>name_tag</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>name_t</span><span class=special>;</span>
165
166<span class=keyword>struct</span> <span class=identifier>ip_address_tag</span><span class=special>{};</span>
167<span class=keyword>typedef</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>,</span><span class=identifier>tag</span><span class=special>&lt;</span><span class=identifier>ip_address_tag</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>ip_address_t</span><span class=special>;</span>
168</pre></blockquote>
169
170<p>
171Now, <code>name_t</code> and <code>ip_address_t</code> are different
172flyweight classes having separate factories each. Tags are a purely syntactic
173device: any type can be used for tagging inside the <code>tag</code>
174construct, though good style recommends using tag classes with
175descriptive names which are local to the context where the flyweight type
176is being defined.
177</p>
178
179<h2><a name="factories">Factory specification</a></h2>
180
181<p>
182<code>flyweight</code> uses a type of internal component called
183<i>factory</i> whose purpose is to store and retrieve the different values
184flyweight objects refer to at a given time. By default, a factory based on
185a hashed container is used, so that <code>flyweight&lt;T&gt;</code> is
186actually equivalent to
187</p>
188
189<blockquote><pre>
190<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>hashed_factory</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
191</pre></blockquote>
192
193<p>
194where <code>hashed_factory</code> is a so-called <i>factory specifier</i>.
195Boost.Flyweight provides several predefined factory specifiers, which not
196only let the user select the specific type of factory used, but also
197accept their own template arguments to customize each factory.
198</p>
199
200<h3><a name="factory_types">Types involved in the configuration of factories</a></h3>
201
202<p>
203A given <code>flyweight</code> instantiation has associated
204<code>flyweight::key_type</code>
205and <code>flyweight::value_type</code> types (which are equal in the case
206of regular flyweights or different if <a href="key_value.html">key-value
207flyweights</a>
208are used). Also, there is an internal <code>Entry</code> type which
209corresponds to the type of the objects actually stored in the factory:
210<code>Entry</code> contains the shared <code>value_type</code> objects
211of <code>flyweight</code> as well a some internal bookkeeping information;
212also, <code>Entry</code> is implicitly convertible to
213<code>const key_type&amp;</code>, so that factories can rely on
214<code>key_type</code> to look up <code>Entrie</code>s. Since
215<code>Entry</code> is internal to the implementation of <code>flyweight</code>,
216it cannot be directly referred to by the user in the configuration of
217factories. Instead, the proxy
218<a href="../../../mpl/doc/refmanual/placeholders.html"><i>placeholder</i></a>
219type <code>boost::mpl::_1</code> can be used.
220</p>
221
222<h3><a name="hashed_factory"><code>hashed_factory</code></a></h3>
223
224<blockquote>
225<b>Header:</b> <a href="../reference/factories.html#hashed_factory_synopsis"><code>"boost/flyweight/hashed_factory.hpp"</code></a><br>
226<b>Syntax:</b> <code>hashed_factory&lt;[Hash[,Pred[,Allocator]]]&gt;</code>
227</blockquote>
228
229<p>
230This specifier, which Boost.Flyweight takes by default, controls the usage of a
231factory internally based in a hash container. Values are determined to be
232equivalent by means of the
233<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html"><code>Binary
234Predicate</code></a> <code>Pred</code>, and indexed into the factory container
235using <code>Hash</code>, which is assumed to be a <i>hash function</i>,
236i.e. a
237<a href="http://www.sgi.com/tech/stl/UnaryFunction.html"><code>Unary
238Function</code></a> assigning to each value a hash identifier of
239type <code>std::size_t</code>. The <code>Allocator</code> parameter is
240used by the factory container for its memory allocation needs. The default
241types for these parameters are such that the expression
242</p>
243
244<blockquote><pre>
245<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>hashed_factory</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
246</pre></blockquote>
247
248<p>
249is equivalent to
250</p>
251
252<blockquote><pre>
253<span class=identifier>flyweight</span><span class=special>&lt;</span>
254 <span class=identifier>T</span><span class=special>,</span>
255 <span class=identifier>hashed_factory</span><span class=special>&lt;</span>
256 <span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special>&lt;</span><span class=identifier>key_value</span><span class=special>&gt;,</span>
257 <span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special>&lt;</span><span class=identifier>key_value</span><span class=special>&gt;,</span>
258 <span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>&gt;</span>
259 <span class=special>&gt;</span>
260<span class=special>&gt;</span>
261</pre></blockquote>
262
263<p>
264where <code>key_type</code> is the key type of the flyweight and
265<code>boost::mpl::_1</code>, as explained above, stands for the
266internal <code>Entry</code> type of the elements stored in the factory.
267Suppose we would like to configure <code>hashed_factory</code> for
268a <code>std::string</code> flyweight with
269a special hash predicate <code>special_hash</code> and a custom allocator
270<code>custom_allocator</code>; this would be specified as follows:
271</p>
272
273<blockquote><pre>
274<span class=identifier>flyweight</span><span class=special>&lt;</span>
275 <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
276 <span class=identifier>hashed_factory</span><span class=special>&lt;</span>
277 <span class=identifier>special_hash</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>
278 <span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special>&lt;</span><span class=identifier>key_value</span><span class=special>&gt;,</span>
279 <span class=identifier>custom_allocator</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>&gt;</span>
280 <span class=special>&gt;</span>
281<span class=special>&gt;</span>
282</pre></blockquote>
283
284<h3><a name="set_factory"><code>set_factory</code></a></h3>
285
286<blockquote>
287<b>Header:</b> <a href="../reference/factories.html#set_factory_synopsis"><code>"boost/flyweight/set_factory.hpp"</code></a><br>
288<b>Syntax:</b> <code>set_factory&lt;[Compare[,Allocator]]&gt;</code>
289</blockquote>
290
291<p>
292<code>set_factory</code> resorts to an <code>std::set</code>-like ordered
293container for the implementation of the flyweight factory.
294<code>Compare</code> must be a
295<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html"><code>Strict
296Weak Ordering</code></a> on the value type <code>flyweight</code> is
297acting upon; as is customary with STL ordered containers, two values
298are considered equivalent if none is less than the other according to <code>Pred</code>.
299<code>Allocator</code> is an allocator type passed along to the factory
300internal container for its memory-related tasks. When default parameters are
301used, the expression
302</p>
303
304<blockquote><pre>
305<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>set_factory</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
306</pre></blockquote>
307
308<p>
309is equivalent to
310</p>
311
312<blockquote><pre>
313<span class=identifier>flyweight</span><span class=special>&lt;</span>
314 <span class=identifier>T</span><span class=special>,</span>
315 <span class=identifier>set_factory</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>key_type</span><span class=special>&gt;,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>&gt;</span> <span class=special>&gt;</span>
316<span class=special>&gt;</span>
317</pre></blockquote>
318
319<p>
320Usual tradeoffs arising in the comparison of ordered and hashed containers
321also apply when choosing between <code>set_factory</code> and
322<code>hashed_factory</code>:
323so, set-based lookup and insertion of values are generally slower than those based on hashing,
324but the latter can be affected by pathological worst-case scenarios with very
325poor performance.
326</p>
327
328<h3><a name="assoc_container_factory"><code>assoc_container_factory</code></a></h3>
329
330<blockquote>
331<b>Header:</b> <a href="../reference/factories.html#assoc_container_factory_synopsis"><code>"boost/flyweight/assoc_container_factory.hpp"</code></a><br>
332<b>Syntax:</b> <code>assoc_container_factory&lt;ContainerSpecifier&gt;</code>
333</blockquote>
334
335<p>
336This specifier can be seen as a generalization of
337<code>hashed_factory</code> and <code>set_factory</code> where the user
338supplies the exact type of container on which the factory is based.
339The way in which the container is specified might seem at first a little
340daunting to those unfamiliar with the
341<a href="../../../mpl/doc/index.html">Boost MPL Library</a>:
342<code>ContainerSpecifier</code> must be an
343<a href="lambda_expressions.html"><code>MPL Lambda
344Expression</code></a> such that, when invoked with the
345types <code>Entry</code> and <code>key_type</code>
346explained <a href="#factory_types">above</a>, it produces the type of
347a container of <code>Entry</code> elements satisfying the following
348requirements:
349<ol>
350 <li>The container type must be a model of
351 <a href="http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html"><code>Unique
352 Associative Container</code></a> where equivalence of <code>Entry</code>s
353 is determined by the <code>key_type</code> values the entries are convertible
354 to .
355 </li>
356 <li>The container must be <i>stable</i>, i.e. its iterators must remain valid
357 after insert and erase operations. Note that this condition is not met by
358 many existing implementations of hashed containers that invalidate iterators
359 upon a rehashing operation.
360 </li>
361</ol>
362</p>
363
364<p>
365Let us see what a container specifier looks like with an example.
366Suppose we have our own ordered container like the following:
367</p>
368
369<blockquote><pre>
370<span class=keyword>template</span><span class=special>&lt;</span>
371 <span class=keyword>typename</span> <span class=identifier>Elem</span><span class=special>,</span>
372 <span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>Elem</span><span class=special>&gt;,</span>
373 <span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span><span class=identifier>Elem</span><span class=special>&gt;</span>
374<span class=special>&gt;</span>
375<span class=keyword>class</span> <span class=identifier>ultrafast_set</span>
376<span class=special>{</span>
377 <span class=special>...</span>
378<span class=special>};</span>
379</pre></blockquote>
380
381<p>
382Then <code>ultrafast_set</code> can be plugged into
383<code>assoc_container_factory</code> like this:
384</p>
385
386<blockquote><pre>
387<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span>
388 <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
389 <span class=identifier>assoc_container_factory</span><span class=special>&lt;</span>
390 <span class=comment>// MPL lambda expression follows</span>
391 <b><span class=identifier>ultrafast_set</span><span class=special>&lt;</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</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></b>
392 <span class=special>&gt;</span>
393<span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
394</pre></blockquote>
395
396<p>
397As has been explained, <code>mpl::_1</code> is a so-called MPL
398placeholder standing as a "slot" to be replaced with
399<code>Entry</code> by the internal machinery of Boost.Flyweight.
400Note that we have not
401relied on the default argument of <code>ultrafast_set</code> for
402<code>Compare</code> and instead we have provided a fixed
403instantiation for <code>std::string</code>: this is so because
404requirements state that the type with which <code>ContainerSpecifier</code>
405will be filled in internally is convertible to <code>const key_type&amp;</code>
406(here <code>const std::string&amp;</code>), and it is based on
407<code>key_type</code> that lookup and equivalence of entries
408should be determined. On the other hand,
409the default argument for the <code>Allocator</code> parameter works
410just fine, as is more apparent if we write it down explicitly:
411</p>
412
413<blockquote><pre>
414<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span>
415 <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
416 <span class=identifier>assoc_container_factory</span><span class=special>&lt;</span>
417 <b><span class=identifier>ultrafast_set</span><span class=special>&lt;</span>
418 <span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</span>
419 <span class=identifier>std</span><span class=special>::</span><span class=identifier>less</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>
420 <span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>&gt;</span>
421 <span class=special>&gt;</span>
422 <span class=special>&gt;</span></b>
423<span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
424</pre></blockquote>
425
426<h2><a name="holders">Holder specification</a></h2>
427
428<p>
429Each flyweight type, that is, each distinct instantiation of the class
430template <code>flyweight</code>, is associated with exactly one factory
431object. In most cases, how this factory object is created is of little
432importance to the user of Boost.Flyweight, but there are special
433circumstances where control of this aspect is necessary. An internal
434component called <i>holder</i> is in charge of instantiating the
435factory class and some other internal information; this component is
436stipulated by means of a <i>holder specifier</i>, <code>static_holder</code>
437being the default one.
438</p>
439
440<h3><a name="static_holder"><code>static_holder</code></a></h3>
441
442<blockquote>
443<b>Header:</b> <a href="../reference/holders.html#static_holder_synopsis"><code>"boost/flyweight/static_holder.hpp"</code></a><br>
444<b>Syntax:</b> <code>static_holder</code>
445</blockquote>
446
447<p>
448This the default holder specifier of Boost.Flyweight, and produces
449holders where the unique factory lives as a local static variable of the
450program.
451</p>
452
453<h3><a name="intermodule_holder"><code>intermodule_holder</code></a></h3>
454
455<blockquote>
456<b>Header:</b> <a href="../reference/holders.html#intermodule_holder_synopsis"><code>"boost/flyweight/intermodule_holder.hpp"</code></a><br>
457<b>Syntax:</b> <code>intermodule_holder</code>
458</blockquote>
459
460<p>
461In most C++ environments, static variables do not mix well with
462dynamically loaded modules in the sense that instances of the same
463static variable can be duplicated across different modules, even
464though by definition the variable should be unique. In many
465cases, this duplication goes unnoticed if the modules do not communicate
466between each other using the affected types, but consider this
467case where such communication does happen:
468</p>
469
470<blockquote><pre>
471<span class=comment>// module 1</span>
472
473<span class=keyword>typedef</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>flyweight_string</span><span class=special>;</span>
474
475<span class=comment>// produce_string is exported so that it can be dynamically
476// linked</span>
477
478<span class=identifier>flyweight_string</span> <span class=identifier>produce_string</span><span class=special>()</span>
479<span class=special>{</span>
480 <span class=keyword>return</span> <span class=identifier>flyweight_string</span><span class=special>(</span><span class=string>&quot;boost&quot;</span><span class=special>);</span>
481<span class=special>}</span>
482</pre></blockquote>
483
484<blockquote><pre>
485<span class=comment>// main program</span>
486
487<span class=keyword>typedef</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>flyweight_string</span><span class=special>;</span>
488
489<span class=keyword>int</span> <span class=identifier>main</span><span class=special>()</span>
490<span class=special>{</span>
491 <span class=special>...</span> <span class=comment>// import module 1</span>
492
493 <span class=identifier>flyweight_string</span> <span class=identifier>str1</span><span class=special>=</span><span class=identifier>produce_string</span><span class=special>();</span>
494 <span class=identifier>flyweight_string</span> <span class=identifier>str2</span><span class=special>(</span><span class=string>&quot;boost&quot;</span><span class=special>);</span>
495 <span class=identifier>assert</span><span class=special>(</span><span class=identifier>str1</span><span class=special>==</span><span class=identifier>str2</span><span class=special>);</span>
496<span class=special>}</span>
497</pre></blockquote>
498
499<p>
500In many environments, this program results in an assertion
501failure because the flyweight factory object used
502by <code>flyweight_string</code> as seen within module 1 is
503not the same factory object as seen within the main program: hence
504the value representations internally pointed to by <code>str1</code>
505and <code>str2</code> will differ and will be mistakenly
506considered as not equal. Many other problems might arise
507due to factory duplication, including undefined behavior.
508</p>
509
510<p>
511<code>intermodule_holder</code> specifies a factory holder which
512is capable of avoiding the duplication problem and ensuring that
513all modules of a program are using the same factory instance.
514To fix the example above, it suffices to redefine
515<code>flyweight_string</code> in both modules as:
516</p>
517
518<blockquote><pre>
519<span class=keyword>typedef</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>,</span><span class=identifier><b>intermodule_holder</b></span><span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
520</pre></blockquote>
521
522<p>
523<code>intermodule_holder</code> is considerably more onerous than
524<code>static_holder</code> in terms of compilation times and
525introduces a non-negligible overhead at program start-up, so its use
526should be reserved to the situations where it is really necessary.
527</p>
528
529
530<h2><a name="locking">Locking policies</a></h2>
531
532<p>
533The internal factory associated to each <code>flyweight</code>
534type is a shared resource and as such access to it must be properly
535synchronized in multithreaded environments. A <i>locking policy</i>
536specifies the synchronization mechanisms to be used for this purpose.
537</p>
538
539<h3><a name="simple_locking"><code>simple_locking</code></a></h3>
540
541<blockquote>
542<b>Header:</b> <a href="../reference/locking.html#simple_locking_synopsis"><code>"boost/flyweight/simple_locking.hpp"</code></a><br>
543<b>Syntax:</b> <code>simple_locking</code>
544</blockquote>
545
546<p>
547This is the default locking policy. It specifies the simplest native
548synchronization primitives provided by the operating system, whenever
549available.
550</p>
551
552<h3><a name="no_locking"><code>no_locking</code></a></h3>
553
554<blockquote>
555<b>Header:</b> <a href="../reference/locking.html#no_locking_synopsis"><code>"boost/flyweight/no_locking.hpp"</code></a><br>
556<b>Syntax:</b> <code>no_locking</code>
557</blockquote>
558
559<p>
560No synchronization is enforced so that irrestricted internal access
561to the implementation shared resources is allowed.
562Selecting <code>no_locking</code> results in somewhat faster execution than
563the default <code>simple_locking</code>, but it renders the type
564thread-unsafe, which can have catastrophic consequences.
565This policy should not be used except in single-threaded environments or
566when there is an absolute guarantee that the particular <code>flyweight</code>
567type will not be used in a concurrent scenario.
568</p>
569
570<h2><a name="tracking">Tracking policies</a></h2>
571
572<p>
573A <i>tracking policy</i> controls the lifetimes of the <code>flyweight</code>
574objects and can act based on this information. For instance, a suitable
575tracking mechanism can determine when a given value stored in the factory
576can be safely erased because it is no longer referenced by any
577<code>flyweight</code>; this is precisely what the default tracking policy,
578<code>refcounted</code>, does.
579</p>
580
581<h3><a name="refcounted"><code>refcounted</code></a></h3>
582
583<blockquote>
584<b>Header:</b> <a href="../reference/tracking.html#refcounted_synopsis"><code>"boost/flyweight/refcounted.hpp"</code></a><br>
585<b>Syntax:</b> <code>refcounted</code>
586</blockquote>
587
588<p>
589This tracking policy determines that values stored in the factory be
590equipped with reference counting mechanisms so that a factory entry is
591erased when the last <code>flyweight</code> object associated to it
592is destroyed.
593</p>
594
595<h3><a name="no_tracking"><code>no_tracking</code></a></h3>
596
597<blockquote>
598<b>Header:</b> <a href="../reference/tracking.html#no_tracking_synopsis"><code>"boost/flyweight/no_tracking.hpp"</code></a><br>
599<b>Syntax:</b> <code>no_tracking</code>
600</blockquote>
601
602<p>
603No flyweight tracking is done when this policy is selected, which implies
604that the values stored in the factory remain in it until program termination.
605As compared with <code>refcounted</code>, <code>no_tracking</code> presents
606advantages and drawbacks. The benefits are:
607<ul>
608 <li>Non-tracked flyweight objects are faster to pass around than refcounted ones.</li>
609 <li>There is some reduction in memory usage due to the
610 absence of reference counters.</li>
611</ul>
612whereas potential drawbacks of using <code>no_tracking</code> include:
613<ul>
614 <li>The number of unused entries stored in the factory can keep growing
615 during the program lifetime, which can become a problem for certain
616 patterns of flyweight creation where the set of active values "drifts"
617 over time.</li>
618 <li>There can be a potential delay during program termination, since
619 it is then when all the factory entries get destroyed at once.</li>
620</ul>
621</p>
622
623<hr>
624
625<div class="prev_link"><a href="key_value.html"><img src="../prev.gif" alt="key-value flyweights" border="0"><br>
626Key-value flyweights
627</a></div>
628<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br>
629Boost.Flyweight tutorial
630</a></div>
631<div class="next_link"><a href="extension.html"><img src="../next.gif" alt="extending Boost.Flyweight" border="0"><br>
632Extending Boost.Flyweight
633</a></div><br clear="all" style="clear: all;">
634
635<br>
636
637<p>Revised November 8th 2008</p>
638
639<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
640Distributed under the Boost Software
641License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
642LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
643http://www.boost.org/LICENSE_1_0.txt</a>)
644</p>
645
646</body>
647</html>