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