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><</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> 106or 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> 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><</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> 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><</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> 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><</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> 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<T></code> is 186actually 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> 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&</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<[Hash[,Pred[,Allocator]]]></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="https://boost.org/sgi/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="https://boost.org/sgi/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><</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> 249is 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> 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><</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 293container for the implementation of the flyweight factory. 294<code>Compare</code> must be a 295<a href="https://boost.org/sgi/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><</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> 309is 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> 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<ContainerSpecifier></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="https://boost.org/sgi/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><</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> 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><</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> 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&</code> 406(here <code>const std::string&</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><</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> 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><</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> 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><</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 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 April 24th 2019</p> 638 639<p>© Copyright 2006-2019 Joaquín M López Muñ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> 648