]>
Commit | Line | Data |
---|---|---|
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> | |
19 | Key-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> | |
22 | Boost.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> | |
25 | Extending 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> | |
71 | Most of the time, <code>flyweight</code> default configuration is just good | |
72 | enough and the user need not care about further tuning of her <code>flyweight</code> | |
73 | instantiations; however, when the necessity for more control over Boost.Flyweight | |
74 | behavior arises, comprehensive mechanisms are provided to select, configure and | |
75 | even 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> | |
94 | The <code>flyweight</code> class template features a "smart" specification | |
95 | interface by which the configuration aspects can be provided as optional template arguments | |
96 | in whatever order the user pleases. For instance, a tagged <code>flyweight</code> | |
97 | of <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><</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><</span><span class=identifier>label_t</span><span class=special>>,</span> <span class=identifier>set_factory</span><span class=special><>,</span> <span class=identifier>no_tracking</span> <span class=special>></span> | |
103 | </pre></blockquote> | |
104 | ||
105 | <p> | |
106 | or like this: | |
107 | </p> | |
108 | ||
109 | <blockquote><pre> | |
110 | <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>no_tracking</span><span class=special>,</span> <span class=identifier>tag</span><span class=special><</span><span class=identifier>label_t</span><span class=special>>,</span> <span class=identifier>set_factory</span><span class=special><></span> <span class=special>></span> | |
111 | </pre></blockquote> | |
112 | ||
113 | <p> | |
114 | or in any other order; only <code>std::string</code> is required to occupy | |
115 | the first place in the specification. | |
116 | </p> | |
117 | ||
118 | <h3><a name="header_inclusion">Header inclusion</a></h3> | |
119 | ||
120 | <p> | |
121 | The example code shown at the <a href="basics.html#intro">introductory section</a> | |
122 | uses the | |
123 | <a href="../reference/index.html#flyweight_synopsis"><code>"boost/flyweight.hpp"</code></a> | |
124 | convenience 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><</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>></span> <span class=comment>// class template flyweight</span> | |
130 | <span class=preprocessor>#include</span> <span class=special><</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>></span> <span class=comment>// hashed flyweight factory</span> | |
131 | <span class=preprocessor>#include</span> <span class=special><</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>></span> <span class=comment>// regular factory instantiation</span> | |
132 | <span class=preprocessor>#include</span> <span class=special><</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>></span> <span class=comment>// simple locking policy</span> | |
133 | <span class=preprocessor>#include</span> <span class=special><</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>></span> <span class=comment>// refcounting tracking policy</span> | |
134 | </pre></blockquote> | |
135 | ||
136 | <p> | |
137 | When using components other than these, their specific headers must be | |
138 | explicitly included. | |
139 | </p> | |
140 | ||
141 | <h2><a name="tagging">Tagging</a></h2> | |
142 | ||
143 | <p> | |
144 | Consider the following two types: | |
145 | </p> | |
146 | ||
147 | <blockquote><pre> | |
148 | <span class=keyword>typedef</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>name_t</span><span class=special>;</span> | |
149 | <span class=keyword>typedef</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>ip_address_t</span><span class=special>;</span> | |
150 | </pre></blockquote> | |
151 | ||
152 | <p> | |
153 | Although technically both types are identical, this is so by virtue of | |
154 | coincidence, as there is no sensible relation between names and IP addresses. | |
155 | Internally, the fact that <code>name_t</code> and <code>ip_address_t</code> | |
156 | are the same flyweight type causes values of both classes to be stored together | |
157 | in the same flyweight factory, although their respective ranges | |
158 | are not expected to overlap. <i>Tagging</i> can be used to turn these | |
159 | into 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><</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><</span><span class=identifier>name_tag</span><span class=special>></span> <span class=special>></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><</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><</span><span class=identifier>ip_address_tag</span><span class=special>></span> <span class=special>></span> <span class=identifier>ip_address_t</span><span class=special>;</span> | |
168 | </pre></blockquote> | |
169 | ||
170 | <p> | |
171 | Now, <code>name_t</code> and <code>ip_address_t</code> are different | |
172 | flyweight classes having separate factories each. Tags are a purely syntactic | |
173 | device: any type can be used for tagging inside the <code>tag</code> | |
174 | construct, though good style recommends using tag classes with | |
175 | descriptive names which are local to the context where the flyweight type | |
176 | is 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 | |
184 | flyweight objects refer to at a given time. By default, a factory based on | |
185 | a hashed container is used, so that <code>flyweight<T></code> is | |
186 | actually equivalent to | |
187 | </p> | |
188 | ||
189 | <blockquote><pre> | |
190 | <span class=identifier>flyweight</span><span class=special><</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>hashed_factory</span><span class=special><></span> <span class=special>></span> | |
191 | </pre></blockquote> | |
192 | ||
193 | <p> | |
194 | where <code>hashed_factory</code> is a so-called <i>factory specifier</i>. | |
195 | Boost.Flyweight provides several predefined factory specifiers, which not | |
196 | only let the user select the specific type of factory used, but also | |
197 | accept 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> | |
203 | A given <code>flyweight</code> instantiation has associated | |
204 | <code>flyweight::key_type</code> | |
205 | and <code>flyweight::value_type</code> types (which are equal in the case | |
206 | of regular flyweights or different if <a href="key_value.html">key-value | |
207 | flyweights</a> | |
208 | are used). Also, there is an internal <code>Entry</code> type which | |
209 | corresponds to the type of the objects actually stored in the factory: | |
210 | <code>Entry</code> contains the shared <code>value_type</code> objects | |
211 | of <code>flyweight</code> as well a some internal bookkeeping information; | |
212 | also, <code>Entry</code> is implicitly convertible to | |
213 | <code>const key_type&</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>, | |
216 | it cannot be directly referred to by the user in the configuration of | |
217 | factories. Instead, the proxy | |
218 | <a href="../../../mpl/doc/refmanual/placeholders.html"><i>placeholder</i></a> | |
219 | type <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<[Hash[,Pred[,Allocator]]]></code> | |
227 | </blockquote> | |
228 | ||
229 | <p> | |
230 | This specifier, which Boost.Flyweight takes by default, controls the usage of a | |
231 | factory internally based in a hash container. Values are determined to be | |
232 | equivalent by means of the | |
233 | <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html"><code>Binary | |
234 | Predicate</code></a> <code>Pred</code>, and indexed into the factory container | |
235 | using <code>Hash</code>, which is assumed to be a <i>hash function</i>, | |
236 | i.e. a | |
237 | <a href="http://www.sgi.com/tech/stl/UnaryFunction.html"><code>Unary | |
238 | Function</code></a> assigning to each value a hash identifier of | |
239 | type <code>std::size_t</code>. The <code>Allocator</code> parameter is | |
240 | used by the factory container for its memory allocation needs. The default | |
241 | types for these parameters are such that the expression | |
242 | </p> | |
243 | ||
244 | <blockquote><pre> | |
245 | <span class=identifier>flyweight</span><span class=special><</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>hashed_factory</span><span class=special><></span> <span class=special>></span> | |
246 | </pre></blockquote> | |
247 | ||
248 | <p> | |
249 | is equivalent to | |
250 | </p> | |
251 | ||
252 | <blockquote><pre> | |
253 | <span class=identifier>flyweight</span><span class=special><</span> | |
254 | <span class=identifier>T</span><span class=special>,</span> | |
255 | <span class=identifier>hashed_factory</span><span class=special><</span> | |
256 | <span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special><</span><span class=identifier>key_value</span><span class=special>>,</span> | |
257 | <span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special><</span><span class=identifier>key_value</span><span class=special>>,</span> | |
258 | <span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special><</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>></span> | |
259 | <span class=special>></span> | |
260 | <span class=special>></span> | |
261 | </pre></blockquote> | |
262 | ||
263 | <p> | |
264 | where <code>key_type</code> is the key type of the flyweight and | |
265 | <code>boost::mpl::_1</code>, as explained above, stands for the | |
266 | internal <code>Entry</code> type of the elements stored in the factory. | |
267 | Suppose we would like to configure <code>hashed_factory</code> for | |
268 | a <code>std::string</code> flyweight with | |
269 | a 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><</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><</span> | |
277 | <span class=identifier>special_hash</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>,</span> | |
278 | <span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special><</span><span class=identifier>key_value</span><span class=special>>,</span> | |
279 | <span class=identifier>custom_allocator</span><span class=special><</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>></span> | |
280 | <span class=special>></span> | |
281 | <span class=special>></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<[Compare[,Allocator]]></code> | |
289 | </blockquote> | |
290 | ||
291 | <p> | |
292 | <code>set_factory</code> resorts to an <code>std::set</code>-like ordered | |
293 | container 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 | |
296 | Weak Ordering</code></a> on the value type <code>flyweight</code> is | |
297 | acting upon; as is customary with STL ordered containers, two values | |
298 | are 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 | |
300 | internal container for its memory-related tasks. When default parameters are | |
301 | used, the expression | |
302 | </p> | |
303 | ||
304 | <blockquote><pre> | |
305 | <span class=identifier>flyweight</span><span class=special><</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>set_factory</span><span class=special><></span> <span class=special>></span> | |
306 | </pre></blockquote> | |
307 | ||
308 | <p> | |
309 | is equivalent to | |
310 | </p> | |
311 | ||
312 | <blockquote><pre> | |
313 | <span class=identifier>flyweight</span><span class=special><</span> | |
314 | <span class=identifier>T</span><span class=special>,</span> | |
315 | <span class=identifier>set_factory</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special><</span><span class=identifier>key_type</span><span class=special>>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special><</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>></span> <span class=special>></span> | |
316 | <span class=special>></span> | |
317 | </pre></blockquote> | |
318 | ||
319 | <p> | |
320 | Usual tradeoffs arising in the comparison of ordered and hashed containers | |
321 | also apply when choosing between <code>set_factory</code> and | |
322 | <code>hashed_factory</code>: | |
323 | so, set-based lookup and insertion of values are generally slower than those based on hashing, | |
324 | but the latter can be affected by pathological worst-case scenarios with very | |
325 | poor 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<ContainerSpecifier></code> | |
333 | </blockquote> | |
334 | ||
335 | <p> | |
336 | This specifier can be seen as a generalization of | |
337 | <code>hashed_factory</code> and <code>set_factory</code> where the user | |
338 | supplies the exact type of container on which the factory is based. | |
339 | The way in which the container is specified might seem at first a little | |
340 | daunting 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 | |
344 | Expression</code></a> such that, when invoked with the | |
345 | types <code>Entry</code> and <code>key_type</code> | |
346 | explained <a href="#factory_types">above</a>, it produces the type of | |
347 | a container of <code>Entry</code> elements satisfying the following | |
348 | requirements: | |
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> | |
365 | Let us see what a container specifier looks like with an example. | |
366 | Suppose we have our own ordered container like the following: | |
367 | </p> | |
368 | ||
369 | <blockquote><pre> | |
370 | <span class=keyword>template</span><span class=special><</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><</span><span class=identifier>Elem</span><span class=special>>,</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><</span><span class=identifier>Elem</span><span class=special>></span> | |
374 | <span class=special>></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> | |
382 | Then <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><</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><</span> | |
390 | <span class=comment>// MPL lambda expression follows</span> | |
391 | <b><span class=identifier>ultrafast_set</span><span class=special><</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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=special>></span></b> | |
392 | <span class=special>></span> | |
393 | <span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> | |
394 | </pre></blockquote> | |
395 | ||
396 | <p> | |
397 | As has been explained, <code>mpl::_1</code> is a so-called MPL | |
398 | placeholder standing as a "slot" to be replaced with | |
399 | <code>Entry</code> by the internal machinery of Boost.Flyweight. | |
400 | Note that we have not | |
401 | relied on the default argument of <code>ultrafast_set</code> for | |
402 | <code>Compare</code> and instead we have provided a fixed | |
403 | instantiation for <code>std::string</code>: this is so because | |
404 | requirements state that the type with which <code>ContainerSpecifier</code> | |
405 | will be filled in internally is convertible to <code>const key_type&</code> | |
406 | (here <code>const std::string&</code>), and it is based on | |
407 | <code>key_type</code> that lookup and equivalence of entries | |
408 | should be determined. On the other hand, | |
409 | the default argument for the <code>Allocator</code> parameter works | |
410 | just 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><</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><</span> | |
417 | <b><span class=identifier>ultrafast_set</span><span class=special><</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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>,</span> | |
420 | <span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special><</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>></span> | |
421 | <span class=special>></span> | |
422 | <span class=special>></span></b> | |
423 | <span class=special>></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> | |
429 | Each flyweight type, that is, each distinct instantiation of the class | |
430 | template <code>flyweight</code>, is associated with exactly one factory | |
431 | object. In most cases, how this factory object is created is of little | |
432 | importance to the user of Boost.Flyweight, but there are special | |
433 | circumstances where control of this aspect is necessary. An internal | |
434 | component called <i>holder</i> is in charge of instantiating the | |
435 | factory class and some other internal information; this component is | |
436 | stipulated by means of a <i>holder specifier</i>, <code>static_holder</code> | |
437 | being 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> | |
448 | This the default holder specifier of Boost.Flyweight, and produces | |
449 | holders where the unique factory lives as a local static variable of the | |
450 | program. | |
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> | |
461 | In most C++ environments, static variables do not mix well with | |
462 | dynamically loaded modules in the sense that instances of the same | |
463 | static variable can be duplicated across different modules, even | |
464 | though by definition the variable should be unique. In many | |
465 | cases, this duplication goes unnoticed if the modules do not communicate | |
466 | between each other using the affected types, but consider this | |
467 | case 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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></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>"boost"</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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></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>"boost"</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> | |
500 | In many environments, this program results in an assertion | |
501 | failure because the flyweight factory object used | |
502 | by <code>flyweight_string</code> as seen within module 1 is | |
503 | not the same factory object as seen within the main program: hence | |
504 | the value representations internally pointed to by <code>str1</code> | |
505 | and <code>str2</code> will differ and will be mistakenly | |
506 | considered as not equal. Many other problems might arise | |
507 | due to factory duplication, including undefined behavior. | |
508 | </p> | |
509 | ||
510 | <p> | |
511 | <code>intermodule_holder</code> specifies a factory holder which | |
512 | is capable of avoiding the duplication problem and ensuring that | |
513 | all modules of a program are using the same factory instance. | |
514 | To 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><</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>></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 | |
525 | introduces a non-negligible overhead at program start-up, so its use | |
526 | should 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> | |
533 | The internal factory associated to each <code>flyweight</code> | |
534 | type is a shared resource and as such access to it must be properly | |
535 | synchronized in multithreaded environments. A <i>locking policy</i> | |
536 | specifies 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> | |
547 | This is the default locking policy. It specifies the simplest native | |
548 | synchronization primitives provided by the operating system, whenever | |
549 | available. | |
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> | |
560 | No synchronization is enforced so that irrestricted internal access | |
561 | to the implementation shared resources is allowed. | |
562 | Selecting <code>no_locking</code> results in somewhat faster execution than | |
563 | the default <code>simple_locking</code>, but it renders the type | |
564 | thread-unsafe, which can have catastrophic consequences. | |
565 | This policy should not be used except in single-threaded environments or | |
566 | when there is an absolute guarantee that the particular <code>flyweight</code> | |
567 | type will not be used in a concurrent scenario. | |
568 | </p> | |
569 | ||
570 | <h2><a name="tracking">Tracking policies</a></h2> | |
571 | ||
572 | <p> | |
573 | A <i>tracking policy</i> controls the lifetimes of the <code>flyweight</code> | |
574 | objects and can act based on this information. For instance, a suitable | |
575 | tracking mechanism can determine when a given value stored in the factory | |
576 | can 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> | |
589 | This tracking policy determines that values stored in the factory be | |
590 | equipped with reference counting mechanisms so that a factory entry is | |
591 | erased when the last <code>flyweight</code> object associated to it | |
592 | is 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> | |
603 | No flyweight tracking is done when this policy is selected, which implies | |
604 | that the values stored in the factory remain in it until program termination. | |
605 | As compared with <code>refcounted</code>, <code>no_tracking</code> presents | |
606 | advantages 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> | |
612 | whereas 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> | |
626 | Key-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> | |
629 | Boost.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> | |
632 | Extending 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>© Copyright 2006-2008 Joaquín M López Muñoz. | |
640 | Distributed under the Boost Software | |
641 | License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> | |
642 | LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> | |
643 | http://www.boost.org/LICENSE_1_0.txt</a>) | |
644 | </p> | |
645 | ||
646 | </body> | |
647 | </html> |