extension.html 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  5. <title>Boost.Flyweight Documentation - Tutorial - Extending Boost.Flyweight</title>
  6. <link rel="stylesheet" href="../style.css" type="text/css">
  7. <link rel="start" href="../index.html">
  8. <link rel="prev" href="configuration.html">
  9. <link rel="up" href="index.html">
  10. <link rel="next" href="technical.html">
  11. </head>
  12. <body>
  13. <h1><img src="../../../../boost.png" alt="Boost logo" align=
  14. "middle" width="277" height="86">Boost.Flyweight Tutorial: Extending Boost.Flyweight</h1>
  15. <div class="prev_link"><a href="configuration.html"><img src="../prev.gif" alt="configuring Boost.Flyweight" border="0"><br>
  16. Configuring Boost.Flyweight
  17. </a></div>
  18. <div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br>
  19. Boost.Flyweight tutorial
  20. </a></div>
  21. <div class="next_link"><a href="technical.html"><img src="../next.gif" alt="technical issues" border="0"><br>
  22. Technical issues
  23. </a></div><br clear="all" style="clear: all;">
  24. <hr>
  25. <h2>Contents</h2>
  26. <ul>
  27. <li><a href="#intro">Introduction</a></li>
  28. <li><a href="#factories">Custom factories</a></li>
  29. <li><a href="#holders">Custom holders</a></li>
  30. <li><a href="#locking">Custom locking policies</a></li>
  31. <li><a href="#tracking">Custom tracking policies</a></li>
  32. </ul>
  33. <h2><a name="intro">Introduction</a></h2>
  34. <p>
  35. Boost.Flyweight provides public interface specifications of
  36. its <a href="configuration.html">configurable aspects</a> so that the user
  37. can extend the library by implementing her own components and providing them to
  38. instantiations of the <code>flyweight</code> class template.
  39. </p>
  40. <p>
  41. In most cases there are two types of entities involved in extending a given
  42. aspect of Boost.Flyweight:
  43. <ul>
  44. <li>The component itself (for instance, a factory class template).</li>
  45. <li>The associated <i>component specifier</i>, which is the type
  46. provided as a template argument of a <code>flyweight</code>
  47. instantiation.
  48. </li>
  49. </ul>
  50. For example, the type
  51. <a href="configuration.html#static_holder"><code>static_holder</code></a>
  52. is a holder specifier which is used by <code>flyweight</code> to generate
  53. actual holder classes, in this case instantiations of the class
  54. template
  55. <a href="../reference/holders.html#static_holder_class"><code>static_holder_class</code></a>.
  56. Note that <code>static_holder</code> is a concrete type while
  57. <code>static_holder_class</code> is a class template, so a specifier can be
  58. seen as a convenient way to provide access to a family of related concrete
  59. components (the different possible instantiations of the class template):
  60. <code>flyweight</code> internally selects the particular component
  61. appropriate for its internal needs.
  62. </p>
  63. <h2><a name="factories">Custom factories</a></h2>
  64. <p>
  65. In a way, factories resemble unique associative containers like <code>std::set</code>,
  66. though their expected interface is much more concise:
  67. </p>
  68. <blockquote><pre>
  69. <span class=comment>// example of a possible factory class template</span>
  70. <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>&gt;</span>
  71. <span class=keyword>class</span> <span class=identifier>custom_factory_class</span>
  72. <span class=special>{</span>
  73. <span class=keyword>public</span><span class=special>:</span>
  74. <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>handle_type</span><span class=special>;</span>
  75. <span class=identifier>handle_type</span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
  76. <span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span>
  77. <span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&amp;</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span>
  78. <span class=special>};</span>
  79. </pre></blockquote>
  80. <p>
  81. Factories are parameterized by <code>Entry</code> and <code>Key</code>:
  82. the first is the type of the objects stored, while the second is the public
  83. key type on which <code>flyweight</code> operates (e.g. the <code>std::string</code>
  84. in <code>flyweight&lt;std::string&gt;</code> or
  85. <code>flyweight&lt;key_value&lt;std::string,texture&gt; &gt;</code>). An entry holds a
  86. shared value to which flyweight objects are associated as well as internal bookkeeping information, but from the
  87. point of view of the factory, though, the only fact known about <code>Entry</code>
  88. is that it is implicitly convertible to <code>const Key&amp;</code>, and it is
  89. based on their associated <code>Key</code> that entries are to be considered
  90. equivalent or not. The factory <code>insert()</code>
  91. member function locates a previously stored entry whose
  92. associated <code>Key</code> is equivalent to that of the <code>Entry</code>
  93. object being passed (for some equivalence relation on <code>Key</code> germane to
  94. the factory), or stores the new entry if no equivalent one is found. A
  95. <code>handle_type</code> to the equivalent or newly inserted entry is returned;
  96. this <code>handle_type</code> is a token for further access to an entry via
  97. <code>erase()</code> and <code>entry()</code>. Consult the
  98. <a href="../reference/factories.html#factory">reference</a> for the formal
  99. definition of the <code>Factory</code> concept.
  100. </p>
  101. <p>
  102. Let us see an actual example of realization of a custom factory class. Suppose
  103. we want to trace the different invocations by Boost.Flyweight of the
  104. <code>insert()</code> and <code>erase()</code> member functions: this can be
  105. done by using a custom factory whose member methods emit trace messages
  106. to the program console. We base the implementation of the repository
  107. functionality on a regular <code>std::set</code>:
  108. <blockquote><pre>
  109. <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>&gt;</span>
  110. <span class=keyword>class</span> <span class=identifier>verbose_factory_class</span>
  111. <span class=special>{</span>
  112. <span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special>&lt;</span><span class=identifier>Entry</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>Key</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>store_type</span><span class=special>;</span>
  113. <span class=identifier>store_type</span> <span class=identifier>store</span><span class=special>;</span>
  114. <span class=keyword>public</span><span class=special>:</span>
  115. <span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>store_type</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>handle_type</span><span class=special>;</span>
  116. <span class=identifier>handle_type</span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span>
  117. <span class=special>{</span>
  118. <span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>handle_type</span><span class=special>,</span> <span class=keyword>bool</span><span class=special>&gt;</span> <span class=identifier>p</span><span class=special>=</span><span class=identifier>store</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>x</span><span class=special>);</span>
  119. <span class=keyword>if</span><span class=special>(</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>second</span><span class=special>){</span> <span class=comment>/* new entry */</span>
  120. <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>&lt;&lt;</span><span class=string>&quot;new: &quot;</span><span class=special>&lt;&lt;(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&amp;)</span><span class=identifier>x</span><span class=special>&lt;&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span>
  121. <span class=special>}</span>
  122. <span class=keyword>else</span><span class=special>{</span> <span class=comment>/* existing entry */</span>
  123. <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>&lt;&lt;</span><span class=string>&quot;hit: &quot;</span><span class=special>&lt;&lt;(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&amp;)</span><span class=identifier>x</span><span class=special>&lt;&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span>
  124. <span class=special>}</span>
  125. <span class=keyword>return</span> <span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>;</span>
  126. <span class=special>}</span>
  127. <span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>)</span>
  128. <span class=special>{</span>
  129. <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>&lt;&lt;</span><span class=string>&quot;del: &quot;</span><span class=special>&lt;&lt;(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&amp;)*</span><span class=identifier>h</span><span class=special>&lt;&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span>
  130. <span class=identifier>store</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>h</span><span class=special>);</span>
  131. <span class=special>}</span>
  132. <span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&amp;</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>)</span>
  133. <span class=special>{</span>
  134. <span class=keyword>return</span> <span class=special>*</span><span class=identifier>h</span><span class=special>;</span>
  135. <span class=special>}</span>
  136. <span class=special>};</span>
  137. </pre></blockquote>
  138. <p>
  139. The code deserves some commentaries:
  140. <ul>
  141. <li>
  142. Note that the factory is parameterized by <code>Entry</code>
  143. and <code>Key</code>, as these types are provided internally by Boost.Flyweight
  144. when the factory is instantiated as part of the machinery of <code>flyeight</code>;
  145. but there is nothing to prevent us from having more template parameters for
  146. finer configuration of the factory type: for instance, we could extend
  147. <code>verbose_factory_class</code> to accept some comparison predicate rather than
  148. the default <code>std::less&lt;Key&gt;</code>, or to specify the allocator
  149. used by the internal <code>std::set</code>.
  150. </li>
  151. <li>
  152. The fact that <code>Entry</code> is convertible to <code>const Key&amp;</code>
  153. (which is about the only property known about <code>Entry</code>) is
  154. exploited in the specification of <code>std::less&lt;Key&gt;</code> as
  155. the comparison predicate for the <code>std::set</code> of <code>Entry</code>s
  156. used as the internal repository.
  157. </li>
  158. <li>
  159. As our public <code>handle_type</code> we are simply using an iterator to the
  160. internal <code>std::set</code>.
  161. </li>
  162. </ul>
  163. </p>
  164. <p>
  165. In order to plug a custom factory into the specification of a <code>flyweight</code>
  166. type, we need an associated construct called the <i>factory specifier</i>.
  167. A factory specifier is a
  168. <a href="lambda_expressions.html"><code>Lambda
  169. Expression</code></a> accepting the two argument types <code>Entry</code>
  170. and <code>Key</code> and returning the corresponding factory class:
  171. </p>
  172. <blockquote><pre>
  173. <span class=comment>// Factory specifier (metafunction class version)</span>
  174. <span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span>
  175. <span class=special>{</span>
  176. <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>&gt;</span>
  177. <span class=keyword>struct</span> <span class=identifier>apply</span>
  178. <span class=special>{</span>
  179. <span class=keyword>typedef</span> <span class=identifier>custom_factory_class</span><span class=special>&lt;</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>&gt;</span> <span class=identifier>type</span><span class=special>;</span>
  180. <span class=special>}</span>
  181. <span class=special>};</span>
  182. <span class=comment>// Factory specifier (placeholder version)</span>
  183. <span class=keyword>typedef</span> <span class=identifier>custom_factory_class</span><span class=special>&lt;</span>
  184. <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>
  185. <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_2</span>
  186. <span class=special>&gt;</span> <span class=identifier>custom_factory_specifier</span><span class=special>;</span>
  187. </pre></blockquote>
  188. <p>
  189. There is one last detail: in order to implement <code>flyweight</code>
  190. <a href="configuration.html#free_order_template">free-order template
  191. parameter interface</a>, it is necessary to explicitly tag a
  192. factory specifier as such, so that it can be distinguised from other
  193. types of specifiers. Boost.Flyweight provides three different mechanisms
  194. to do this tagging:
  195. <ol>
  196. <li>Have the specifier derive from the dummy type <code>factory_marker</code>.
  197. Note that this mechanism cannot be used with placeholder expressions.
  198. <blockquote><pre>
  199. <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>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  200. <span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span><span class=special>:</span> <span class=identifier><b>factory_marker</b></span>
  201. <span class=special>{</span>
  202. <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>&gt;</span>
  203. <span class=keyword>struct</span> <span class=identifier>apply</span>
  204. <span class=special>{</span>
  205. <span class=keyword>typedef</span> <span class=identifier>custom_factory_class</span><span class=special>&lt;</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>&gt;</span> <span class=identifier>type</span><span class=special>;</span>
  206. <span class=special>}</span>
  207. <span class=special>};</span>
  208. </pre></blockquote>
  209. </li>
  210. <li>Specialize a special class template called
  211. <a href="../reference/factories.html#is_factory"><code>is_factory</code></a>:
  212. <blockquote><pre>
  213. <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>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  214. <span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span><span class=special>{};</span>
  215. <span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
  216. <span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span>
  217. <span class=keyword>template</span><span class=special>&lt;&gt;</span> <span class=keyword>struct</span> <span class=identifier>is_factory</span><span class=special>&lt;</span><span class=identifier>custom_factory_specifier</span><span class=special>&gt;:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span>
  218. <span class=special>}</span>
  219. <span class=special>}</span>
  220. </pre></blockquote>
  221. </li>
  222. <li>The third mechanism, which is the least intrusive, consists in
  223. wrapping the specifier inside the
  224. <a href="../reference/factories.html#factory_construct"><code>factory</code></a>
  225. construct:
  226. <blockquote><pre>
  227. <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>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  228. <span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span>
  229. <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
  230. <span class=identifier><b>factory</b></span><span class=special>&lt;</span><span class=identifier>custom_factory_specifier</span><span class=special>&gt;</span>
  231. <span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
  232. </pre></blockquote>
  233. </li>
  234. </ol>
  235. </p>
  236. <p>
  237. <a href="../examples.html#example8">Example 8</a> in the examples section develops
  238. in full the <code>verbose_factory_class</code> case sketched above.
  239. </p>
  240. <h2><a name="holders">Custom holders</a></h2>
  241. <p>
  242. A holder is a class with a static member function <code>get()</code> giving
  243. access to a unique instance of a given type <code>C</code>:
  244. </p>
  245. <blockquote><pre>
  246. <span class=comment>// example of a possible holder class template</span>
  247. <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>&gt;</span>
  248. <span class=keyword>class</span> <span class=identifier>custom_holder_class</span>
  249. <span class=special>{</span>
  250. <span class=keyword>public</span><span class=special>:</span>
  251. <span class=keyword>static</span> <span class=identifier>C</span><span class=special>&amp;</span> <span class=identifier>get</span><span class=special>();</span>
  252. <span class=special>};</span>
  253. </pre></blockquote>
  254. <p>
  255. <code>flyweight</code> internally uses a holder to create its associated
  256. factory as well as some other global data. A holder specifier is a
  257. <a href="lambda_expressions.html"><code>Lambda
  258. Expression</code></a> accepting the type <code>C</code> upon which
  259. the associated holder class operates:
  260. </p>
  261. <blockquote><pre>
  262. <span class=comment>// Holder specifier (metafunction class version)</span>
  263. <span class=keyword>struct</span> <span class=identifier>custom_holder_specifier</span>
  264. <span class=special>{</span>
  265. <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>&gt;</span>
  266. <span class=keyword>struct</span> <span class=identifier>apply</span>
  267. <span class=special>{</span>
  268. <span class=keyword>typedef</span> <span class=identifier>custom_holder_class</span><span class=special>&lt;</span><span class=identifier>C</span><span class=special>&gt;</span> <span class=identifier>type</span><span class=special>;</span>
  269. <span class=special>}</span>
  270. <span class=special>};</span>
  271. <span class=comment>// Holder specifier (placeholder version)</span>
  272. <span class=keyword>typedef</span> <span class=identifier>custom_holder_class</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=identifier>custom_factory_specifier</span><span class=special>;</span>
  273. </pre></blockquote>
  274. <p>
  275. As is the case with <a href="#factories">factory specifiers</a>, holder
  276. specifiers must be tagged in order to be properly recognized when
  277. provided to <code>flyweight</code>, and there are three available mechanisms
  278. to do so:
  279. </p>
  280. <blockquote><pre>
  281. <span class=comment>// Alternatives for tagging a holder specifier</span>
  282. <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>holder_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  283. <span class=comment>// 1: Have the specifier derive from holder_marker</span>
  284. <span class=keyword>struct</span> <span class=identifier>custom_holder_specifier</span><span class=special>:</span> <span class=identifier><b>holder_marker</b></span>
  285. <span class=special>{</span>
  286. <span class=special>...</span>
  287. <span class=special>};</span>
  288. <span class=comment>// 2: Specialize the is_holder class template</span>
  289. <span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
  290. <span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span>
  291. <span class=keyword>template</span><span class=special>&lt;&gt;</span> <span class=keyword>struct</span> <span class=identifier>is_holder</span><span class=special>&lt;</span><span class=identifier>custom_holder_specifier</span><span class=special>&gt;:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span>
  292. <span class=special>}}</span>
  293. <span class=comment>// 3: use the holder&lt;&gt; wrapper when passing the specifier
  294. // to flyweight</span>
  295. <span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span>
  296. <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
  297. <span class=identifier><b>holder</b></span><span class=special>&lt;</span><span class=identifier>custom_holder_specifier</span><span class=special>&gt;</span>
  298. <span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
  299. </pre></blockquote>
  300. <h2><a name="locking">Custom locking policies</a></h2>
  301. <p>
  302. A custom locking policy presents the following simple interface:
  303. </p>
  304. <blockquote><pre>
  305. <span class=comment>// example of a custom policy</span>
  306. <span class=keyword>class</span> <span class=identifier>custom_locking</span>
  307. <span class=special>{</span>
  308. <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>mutex_type</span><span class=special>;</span>
  309. <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>lock_type</span><span class=special>;</span>
  310. <span class=special>};</span>
  311. </pre></blockquote>
  312. <p>
  313. where <code>lock_type</code> is used to acquire/release mutexes according to
  314. the <i>scoped lock</i> idiom:
  315. </p>
  316. <blockquote><pre>
  317. <span class=identifier>mutex_type</span> <span class=identifier>m</span><span class=special>;</span>
  318. <span class=special>...</span>
  319. <span class=special>{</span>
  320. <span class=identifier>lock_type</span> <span class=identifier>lk</span><span class=special>(</span><span class=identifier>m</span><span class=special>);</span> <span class=comment>// acquire the mutex
  321. // zone of mutual exclusion, no other thread can acquire the mutex</span>
  322. <span class=special>...</span>
  323. <span class=special>}</span> <span class=comment>// m released at lk destruction</span>
  324. </pre></blockquote>
  325. <p>
  326. Formal definitions for the concepts
  327. <a href="../reference/locking.html#preliminary"><code>Mutex</code></a> and
  328. <a href="../reference/locking.html#preliminary"><code>Scoped Lock</code></a>
  329. are given at the reference. To pass a locking policy as a template argument of
  330. <code>flyweight</code>, the class must be appropriately tagged:
  331. </p>
  332. <blockquote><pre>
  333. <span class=comment>// Alternatives for tagging a locking policy</span>
  334. <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>locking_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  335. <span class=comment>// 1: Have the policy derive from locking_marker</span>
  336. <span class=keyword>struct</span> <span class=identifier>custom_locking</span><span class=special>:</span> <span class=identifier>locking_marker</span>
  337. <span class=special>{</span>
  338. <span class=special>...</span>
  339. <span class=special>};</span>
  340. <span class=comment>// 2: Specialize the is_locking class template</span>
  341. <span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
  342. <span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span>
  343. <span class=keyword>template</span><span class=special>&lt;&gt;</span> <span class=keyword>struct</span> <span class=identifier>is_locking</span><span class=special>&lt;</span><span class=identifier>custom_locking</span><span class=special>&gt;:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span>
  344. <span class=special>}}</span>
  345. <span class=comment>// 3: use the locking&lt;&gt; wrapper when passing the policy
  346. // to flyweight</span>
  347. <span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span>
  348. <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
  349. <span class=identifier>locking</span><span class=special>&lt;</span><span class=identifier>custom_locking</span><span class=special>&gt;</span>
  350. <span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
  351. </pre></blockquote>
  352. <p>
  353. Note that a locking policy is its own specifier, i.e. there is no
  354. additional class to be passed as a proxy for the real component as is
  355. the case with factories and holders.
  356. </p>
  357. <h2><a name="tracking">Custom tracking policies</a></h2>
  358. <p>
  359. Tracking policies contribute some type information to the process of
  360. definition of the internal flyweight factory, and are given access
  361. to that factory to allow for the implementation of the tracking
  362. code. A tracking policy <code>Tracking</code> is defined as a class with
  363. the following nested elements:
  364. <ul>
  365. <li>A type <code>Tracking::entry_type</code>.</li>
  366. <li>A type <code>Tracking::handle_type</code>.</li>
  367. </ul>
  368. Each of these elements build on the preceding one, in the sense that
  369. Boost.Flyweight internal machinery funnels the results produced by an
  370. element into the following:
  371. <ul>
  372. <li><code>Tracking::entry_type</code> is a
  373. <a href="lambda_expressions.html"><code>Lambda
  374. Expression</code></a> accepting two different types named
  375. <code>Value</code> and <code>Key</code> such that
  376. <code>Value</code> is implicitly convertible to
  377. <code>const Key&amp;</code>. The expression is expected
  378. to return
  379. a type implicitly convertible to both <code>const Value&amp;</code>
  380. and <code>const Key&amp;</code>.
  381. <code>Tracking::entry_type</code> corresponds to the actual
  382. type of the entries stored into the
  383. <a href="configuration.html#factory_types">flyweight factory</a>:
  384. by allowing the tracking policy to take part on the definition
  385. of this type it is possible for the policy to add internal
  386. tracking information to the entry data in case this is needed.
  387. If no additional information is required,
  388. the tracking policy can simply return <code>Value</code> as its
  389. <code>Tracking::entry_type</code> type.
  390. </li>
  391. <li>
  392. The binary <a href="lambda_expressions.html"><code>Lambda
  393. Expression</code></a> <code>Tracking::handle_type</code> is invoked
  394. with types <code>InternalHandle</code> and <code>TrackingHandler</code>
  395. to produce a type <code>Handle</code>, which will be used as the handle
  396. type of the flyweight factory.
  397. <a href="../reference/tracking.html#preliminary"><code>TrackingHandler</code></a>
  398. is passed as a template argument to <code>Tracking::handle_type</code>
  399. to offer functionality supporting the implementation of the tracking
  400. code.
  401. </li>
  402. </ul>
  403. So, in order to define the factory of some instantiation
  404. <code>fw_t</code> of <code>flyweight</code>, <code>Tracking::entry_type</code>
  405. is invoked with an internal type <code>Value</code> implicitly convertible
  406. to <code>const fw_t::key_type&amp;</code> to obtain the entry type for the factory,
  407. which must be convertible to both <code>const Value&amp;</code> and
  408. <code>const fw_t::key_type&amp;</code>.
  409. Then, <code>Tracking::handle_type</code> is fed an internal handle
  410. type and a tracking policy helper to produce the factory handle type.
  411. The observant reader might have detected an apparent circularity:
  412. <code>Tracking::handle_type</code> produces the handle type of
  413. the flyweight factory, and at the same time is passed a tracking helper
  414. that grants access to the factory being defined!
  415. The solution to this riddle comes from the realization of the fact that
  416. <code>TrackingHandler</code> is an <i>incomplete
  417. type</i> by the time it is passed to <code>Tracking::handle_type</code>:
  418. only when <code>Handle</code> is instantiated at a later stage will this
  419. type be complete.
  420. </p>
  421. <p>
  422. In order for a tracking policy to be passed to <code>flyweight</code>,
  423. it must be tagged much in the same way as the rest of specifiers.
  424. </p>
  425. <blockquote><pre>
  426. <span class=comment>// Alternatives for tagging a tracking policy</span>
  427. <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>tracking_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  428. <span class=comment>// 1: Have the policy derive from tracking_marker</span>
  429. <span class=keyword>struct</span> <span class=identifier>custom_tracking</span><span class=special>:</span> <span class=identifier><b>tracking_marker</b></span>
  430. <span class=special>{</span>
  431. <span class=special>...</span>
  432. <span class=special>};</span>
  433. <span class=comment>// 2: Specialize the is_tracking class template</span>
  434. <span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
  435. <span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span>
  436. <span class=keyword>template</span><span class=special>&lt;&gt;</span> <span class=keyword>struct</span> <span class=identifier>is_tracking</span><span class=special>&lt;</span><span class=identifier>custom_tracking</span><span class=special>&gt;:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span>
  437. <span class=special>}}</span>
  438. <span class=comment>// 3: use the tracking&lt;&gt; wrapper when passing the policy
  439. // to flyweight</span>
  440. <span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span>
  441. <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
  442. <span class=identifier><b>tracking</b></span><span class=special>&lt;</span><span class=identifier>custom_tracking</span><span class=special>&gt;</span>
  443. <span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
  444. </pre></blockquote>
  445. <p>
  446. Tracking policies are their own specifiers, that is, they are provided directly
  447. as template arguments to the <code>flyweight</code> class template.
  448. </p>
  449. <hr>
  450. <div class="prev_link"><a href="configuration.html"><img src="../prev.gif" alt="configuring Boost.Flyweight" border="0"><br>
  451. Configuring Boost.Flyweight
  452. </a></div>
  453. <div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br>
  454. Boost.Flyweight tutorial
  455. </a></div>
  456. <div class="next_link"><a href="technical.html"><img src="../next.gif" alt="technical issues" border="0"><br>
  457. Technical issues
  458. </a></div><br clear="all" style="clear: all;">
  459. <br>
  460. <p>Revised September 1st 2014</p>
  461. <p>&copy; Copyright 2006-2014 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
  462. Distributed under the Boost Software
  463. License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
  464. LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
  465. http://www.boost.org/LICENSE_1_0.txt</a>)
  466. </p>
  467. </body>
  468. </html>