| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN"> |
| |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
| <title>Boost.Flyweight Documentation - Tutorial - Extending Boost.Flyweight</title> |
| <link rel="stylesheet" href="../style.css" type="text/css"> |
| <link rel="start" href="../index.html"> |
| <link rel="prev" href="configuration.html"> |
| <link rel="up" href="index.html"> |
| <link rel="next" href="technical.html"> |
| </head> |
| |
| <body> |
| <h1><img src="../../../../boost.png" alt="Boost logo" align= |
| "middle" width="277" height="86">Boost.Flyweight Tutorial: Extending Boost.Flyweight</h1> |
| |
| <div class="prev_link"><a href="configuration.html"><img src="../prev.gif" alt="configuring Boost.Flyweight" border="0"><br> |
| Configuring Boost.Flyweight |
| </a></div> |
| <div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br> |
| Boost.Flyweight tutorial |
| </a></div> |
| <div class="next_link"><a href="technical.html"><img src="../next.gif" alt="technical issues" border="0"><br> |
| Technical issues |
| </a></div><br clear="all" style="clear: all;"> |
| |
| <hr> |
| |
| <h2>Contents</h2> |
| |
| <ul> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#factories">Custom factories</a></li> |
| <li><a href="#holders">Custom holders</a></li> |
| <li><a href="#locking">Custom locking policies</a></li> |
| <li><a href="#tracking">Custom tracking policies</a></li> |
| </ul> |
| |
| <h2><a name="intro">Introduction</a></h2> |
| |
| <p> |
| Boost.Flyweight provides public interface specifications of |
| its <a href="configuration.html">configurable aspects</a> so that the user |
| can extend the library by implementing her own components and providing them to |
| instantiations of the <code>flyweight</code> class template. |
| </p> |
| |
| <p> |
| In most cases there are two types of entities involved in extending a given |
| aspect of Boost.Flyweight: |
| <ul> |
| <li>The component itself (for instance, a factory class template).</li> |
| <li>The associated <i>component specifier</i>, which is the type |
| provided as a template argument of a <code>flyweight</code> |
| instantiation. |
| </li> |
| </ul> |
| For example, the type |
| <a href="configuration.html#static_holder"><code>static_holder</code></a> |
| is a holder specifier which is used by <code>flyweight</code> to generate |
| actual holder classes, in this case instantiations of the class |
| template |
| <a href="../reference/holders.html#static_holder_class"><code>static_holder_class</code></a>. |
| Note that <code>static_holder</code> is a concrete type while |
| <code>static_holder_class</code> is a class template, so a specifier can be |
| seen as a convenient way to provide access to a family of related concrete |
| components (the different possible instantiations of the class template): |
| <code>flyweight</code> internally selects the particular component |
| appropriate for its internal needs. |
| </p> |
| |
| <h2><a name="factories">Custom factories</a></h2> |
| |
| <p> |
| In a way, factories resemble unique associative containers like <code>std::set</code>, |
| though their expected interface is much more concise: |
| </p> |
| |
| <blockquote><pre> |
| <span class=comment>// example of a possible factory class template</span> |
| |
| <span class=keyword>template</span><span class=special><</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>></span> |
| <span class=keyword>class</span> <span class=identifier>custom_factory_class</span> |
| <span class=special>{</span> |
| <span class=keyword>public</span><span class=special>:</span> |
| <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>handle_type</span><span class=special>;</span> |
| |
| <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>&</span> <span class=identifier>x</span><span class=special>);</span> |
| <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> |
| <span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</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> |
| <span class=special>};</span> |
| </pre></blockquote> |
| |
| <p> |
| Factories are parameterized by <code>Entry</code> and <code>Key</code>: |
| the first is the type of the objects stored, while the second is the public |
| key type on which <code>flyweight</code> operates (e.g. the <code>std::string</code> |
| in <code>flyweight<std::string></code> or |
| <code>flyweight<key_value<std::string,texture> ></code>). An entry holds a |
| shared value to which flyweight objects are associated as well as internal bookkeeping information, but from the |
| point of view of the factory, though, the only fact known about <code>Entry</code> |
| is that it is implicitly convertible to <code>const Key&</code>, and it is |
| based on their associated <code>Key</code> that entries are to be considered |
| equivalent or not. The factory <code>insert()</code> |
| member function locates a previously stored entry whose |
| associated <code>Key</code> is equivalent to that of the <code>Entry</code> |
| object being passed (for some equivalence relation on <code>Key</code> germane to |
| the factory), or stores the new entry if no equivalent one is found. A |
| <code>handle_type</code> to the equivalent or newly inserted entry is returned; |
| this <code>handle_type</code> is a token for further access to an entry via |
| <code>erase()</code> and <code>entry()</code>. Consult the |
| <a href="../reference/factories.html#factory">reference</a> for the formal |
| definition of the <code>Factory</code> concept. |
| </p> |
| |
| <p> |
| Let us see an actual example of realization of a custom factory class. Suppose |
| we want to trace the different invocations by Boost.Flyweight of the |
| <code>insert()</code> and <code>erase()</code> member functions: this can be |
| done by using a custom factory whose member methods emit trace messages |
| to the program console. We base the implementation of the repository |
| functionality on a regular <code>std::set</code>: |
| |
| <blockquote><pre> |
| <span class=keyword>template</span><span class=special><</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>></span> |
| <span class=keyword>class</span> <span class=identifier>verbose_factory_class</span> |
| <span class=special>{</span> |
| <span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special><</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><</span><span class=identifier>Key</span><span class=special>></span> <span class=special>></span> <span class=identifier>store_type</span><span class=special>;</span> |
| |
| <span class=identifier>store_type</span> <span class=identifier>store</span><span class=special>;</span> |
| |
| <span class=keyword>public</span><span class=special>:</span> |
| <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> |
| |
| <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>&</span> <span class=identifier>x</span><span class=special>)</span> |
| <span class=special>{</span> |
| <span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>handle_type</span><span class=special>,</span> <span class=keyword>bool</span><span class=special>></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> |
| <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> |
| <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special><<</span><span class=string>"new: "</span><span class=special><<(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&)</span><span class=identifier>x</span><span class=special><<</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span> |
| <span class=special>}</span> |
| <span class=keyword>else</span><span class=special>{</span> <span class=comment>/* existing entry */</span> |
| <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special><<</span><span class=string>"hit: "</span><span class=special><<(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&)</span><span class=identifier>x</span><span class=special><<</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span> |
| <span class=special>}</span> |
| <span class=keyword>return</span> <span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>;</span> |
| <span class=special>}</span> |
| |
| <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> |
| <span class=special>{</span> |
| <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special><<</span><span class=string>"del: "</span><span class=special><<(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&)*</span><span class=identifier>h</span><span class=special><<</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span> |
| <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> |
| <span class=special>}</span> |
| |
| <span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</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> |
| <span class=special>{</span> |
| <span class=keyword>return</span> <span class=special>*</span><span class=identifier>h</span><span class=special>;</span> |
| <span class=special>}</span> |
| <span class=special>};</span> |
| </pre></blockquote> |
| |
| <p> |
| The code deserves some commentaries: |
| <ul> |
| <li> |
| Note that the factory is parameterized by <code>Entry</code> |
| and <code>Key</code>, as these types are provided internally by Boost.Flyweight |
| when the factory is instantiated as part of the machinery of <code>flyeight</code>; |
| but there is nothing to prevent us from having more template parameters for |
| finer configuration of the factory type: for instance, we could extend |
| <code>verbose_factory_class</code> to accept some comparison predicate rather than |
| the default <code>std::less<Key></code>, or to specify the allocator |
| used by the internal <code>std::set</code>. |
| </li> |
| <li> |
| The fact that <code>Entry</code> is convertible to <code>const Key&</code> |
| (which is about the only property known about <code>Entry</code>) is |
| exploited in the specification of <code>std::less<Key></code> as |
| the comparison predicate for the <code>std::set</code> of <code>Entry</code>s |
| used as the internal repository. |
| </li> |
| <li> |
| As our public <code>handle_type</code> we are simply using an iterator to the |
| internal <code>std::set</code>. |
| </li> |
| </ul> |
| </p> |
| |
| <p> |
| In order to plug a custom factory into the specification of a <code>flyweight</code> |
| type, we need an associated construct called the <i>factory specifier</i>. |
| A factory specifier is a |
| <a href="lambda_expressions.html"><code>Lambda |
| Expression</code></a> accepting the two argument types <code>Entry</code> |
| and <code>Key</code> and returning the corresponding factory class: |
| </p> |
| |
| <blockquote><pre> |
| <span class=comment>// Factory specifier (metafunction class version)</span> |
| |
| <span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span> |
| <span class=special>{</span> |
| <span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> |
| <span class=keyword>struct</span> <span class=identifier>apply</span> |
| <span class=special>{</span> |
| <span class=keyword>typedef</span> <span class=identifier>custom_factory_class</span><span class=special><</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> <span class=identifier>type</span><span class=special>;</span> |
| <span class=special>}</span> |
| <span class=special>};</span> |
| |
| <span class=comment>// Factory specifier (placeholder version)</span> |
| |
| <span class=keyword>typedef</span> <span class=identifier>custom_factory_class</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=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_2</span> |
| <span class=special>></span> <span class=identifier>custom_factory_specifier</span><span class=special>;</span> |
| </pre></blockquote> |
| |
| <p> |
| There is one last detail: in order to implement <code>flyweight</code> |
| <a href="configuration.html#free_order_template">free-order template |
| parameter interface</a>, it is necessary to explicitly tag a |
| factory specifier as such, so that it can be distinguised from other |
| types of specifiers. Boost.Flyweight provides three different mechanisms |
| to do this tagging: |
| <ol> |
| <li>Have the specifier derive from the dummy type <code>factory_marker</code>. |
| Note that this mechanism cannot be used with placeholder expressions. |
| <blockquote><pre> |
| <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>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> |
| |
| <span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span><span class=special>:</span> <span class=identifier><b>factory_marker</b></span> |
| <span class=special>{</span> |
| <span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> |
| <span class=keyword>struct</span> <span class=identifier>apply</span> |
| <span class=special>{</span> |
| <span class=keyword>typedef</span> <span class=identifier>custom_factory_class</span><span class=special><</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> <span class=identifier>type</span><span class=special>;</span> |
| <span class=special>}</span> |
| <span class=special>};</span> |
| </pre></blockquote> |
| </li> |
| <li>Specialize a special class template called |
| <a href="../reference/factories.html#is_factory"><code>is_factory</code></a>: |
| <blockquote><pre> |
| <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>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> |
| |
| <span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span><span class=special>{};</span> |
| |
| <span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> |
| <span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> |
| |
| <span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_factory</span><span class=special><</span><span class=identifier>custom_factory_specifier</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>true_</span><span class=special>{};</span> |
| |
| <span class=special>}</span> |
| <span class=special>}</span> |
| </pre></blockquote> |
| </li> |
| <li>The third mechanism, which is the least intrusive, consists in |
| wrapping the specifier inside the |
| <a href="../reference/factories.html#factory_construct"><code>factory</code></a> |
| construct: |
| <blockquote><pre> |
| <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>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> |
| |
| <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>factory</b></span><span class=special><</span><span class=identifier>custom_factory_specifier</span><span class=special>></span> |
| <span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> |
| </pre></blockquote> |
| </li> |
| </ol> |
| </p> |
| |
| <p> |
| <a href="../examples.html#example7">Example 7</a> in the examples section develops |
| in full the <code>verbose_factory_class</code> case sketched above. |
| </p> |
| |
| <h2><a name="holders">Custom holders</a></h2> |
| |
| <p> |
| A holder is a class with a static member function <code>get()</code> giving |
| access to a unique instance of a given type <code>C</code>: |
| </p> |
| |
| <blockquote><pre> |
| <span class=comment>// example of a possible holder class template</span> |
| |
| <span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>></span> |
| <span class=keyword>class</span> <span class=identifier>custom_holder_class</span> |
| <span class=special>{</span> |
| <span class=keyword>public</span><span class=special>:</span> |
| <span class=keyword>static</span> <span class=identifier>C</span><span class=special>&</span> <span class=identifier>get</span><span class=special>();</span> |
| <span class=special>};</span> |
| </pre></blockquote> |
| |
| <p> |
| <code>flyweight</code> internally uses a holder to create its associated |
| factory as well as some other global data. A holder specifier is a |
| <a href="lambda_expressions.html"><code>Lambda |
| Expression</code></a> accepting the type <code>C</code> upon which |
| the associated holder class operates: |
| </p> |
| |
| <blockquote><pre> |
| <span class=comment>// Holder specifier (metafunction class version)</span> |
| |
| <span class=keyword>struct</span> <span class=identifier>custom_holder_specifier</span> |
| <span class=special>{</span> |
| <span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>></span> |
| <span class=keyword>struct</span> <span class=identifier>apply</span> |
| <span class=special>{</span> |
| <span class=keyword>typedef</span> <span class=identifier>custom_holder_class</span><span class=special><</span><span class=identifier>C</span><span class=special>></span> <span class=identifier>type</span><span class=special>;</span> |
| <span class=special>}</span> |
| <span class=special>};</span> |
| |
| <span class=comment>// Holder specifier (placeholder version)</span> |
| |
| <span class=keyword>typedef</span> <span class=identifier>custom_holder_class</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=identifier>custom_factory_specifier</span><span class=special>;</span> |
| </pre></blockquote> |
| |
| <p> |
| As is the case with <a href="#factories">factory specifiers</a>, holder |
| specifiers must be tagged in order to be properly recognized when |
| provided to <code>flyweight</code>, and there are three available mechanisms |
| to do so: |
| </p> |
| |
| <blockquote><pre> |
| <span class=comment>// Alternatives for tagging a holder specifier</span> |
| |
| <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>holder_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> |
| |
| <span class=comment>// 1: Have the specifier derive from holder_marker</span> |
| |
| <span class=keyword>struct</span> <span class=identifier>custom_holder_specifier</span><span class=special>:</span> <span class=identifier><b>holder_marker</b></span> |
| <span class=special>{</span> |
| <span class=special>...</span> |
| <span class=special>};</span> |
| |
| <span class=comment>// 2: Specialize the is_holder class template</span> |
| |
| <span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> |
| <span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> |
| |
| <span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_holder</span><span class=special><</span><span class=identifier>custom_holder_specifier</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>true_</span><span class=special>{};</span> |
| |
| <span class=special>}}</span> |
| |
| <span class=comment>// 3: use the holder<> wrapper when passing the specifier |
| // to flyweight</span> |
| |
| <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>holder</b></span><span class=special><</span><span class=identifier>custom_holder_specifier</span><span class=special>></span> |
| <span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> |
| </pre></blockquote> |
| |
| <h2><a name="locking">Custom locking policies</a></h2> |
| |
| <p> |
| A custom locking policy presents the following simple interface: |
| </p> |
| |
| <blockquote><pre> |
| <span class=comment>// example of a custom policy</span> |
| |
| <span class=keyword>class</span> <span class=identifier>custom_locking</span> |
| <span class=special>{</span> |
| <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>mutex_type</span><span class=special>;</span> |
| <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>lock_type</span><span class=special>;</span> |
| <span class=special>};</span> |
| </pre></blockquote> |
| |
| <p> |
| where <code>lock_type</code> is used to acquire/release mutexes according to |
| the <i>scoped lock</i> idiom: |
| </p> |
| |
| <blockquote><pre> |
| <span class=identifier>mutex_type</span> <span class=identifier>m</span><span class=special>;</span> |
| <span class=special>...</span> |
| <span class=special>{</span> |
| <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 |
| // zone of mutual exclusion, no other thread can acquire the mutex</span> |
| <span class=special>...</span> |
| <span class=special>}</span> <span class=comment>// m released at lk destruction</span> |
| </pre></blockquote> |
| |
| <p> |
| Formal definitions for the concepts |
| <a href="../reference/locking.html#preliminary"><code>Mutex</code></a> and |
| <a href="../reference/locking.html#preliminary"><code>Scoped Lock</code></a> |
| are given at the reference. To pass a locking policy as a template argument of |
| <code>flyweight</code>, the class must be appropriately tagged: |
| </p> |
| |
| <blockquote><pre> |
| <span class=comment>// Alternatives for tagging a locking policy</span> |
| |
| <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>locking_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> |
| |
| <span class=comment>// 1: Have the policy derive from locking_marker</span> |
| |
| <span class=keyword>struct</span> <span class=identifier>custom_locking</span><span class=special>:</span> <span class=identifier>locking_marker</span> |
| <span class=special>{</span> |
| <span class=special>...</span> |
| <span class=special>};</span> |
| |
| <span class=comment>// 2: Specialize the is_locking class template</span> |
| |
| <span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> |
| <span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> |
| |
| <span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_locking</span><span class=special><</span><span class=identifier>custom_locking</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>true_</span><span class=special>{};</span> |
| |
| <span class=special>}}</span> |
| |
| <span class=comment>// 3: use the locking<> wrapper when passing the policy |
| // to flyweight</span> |
| |
| <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>locking</span><span class=special><</span><span class=identifier>custom_locking</span><span class=special>></span> |
| <span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> |
| </pre></blockquote> |
| |
| <p> |
| Note that a locking policy is its own specifier, i.e. there is no |
| additional class to be passed as a proxy for the real component as is |
| the case with factories and holders. |
| </p> |
| |
| <h2><a name="tracking">Custom tracking policies</a></h2> |
| |
| <p> |
| Tracking policies contribute some type information to the process of |
| definition of the internal flyweight factory, and are given access |
| to that factory to allow for the implementation of the tracking |
| code. A tracking policy <code>Tracking</code> is defined as a class with |
| the following nested elements: |
| <ul> |
| <li>A type <code>Tracking::entry_type</code>.</li> |
| <li>A type <code>Tracking::handle_type</code>.</li> |
| </ul> |
| Each of these elements build on the preceding one, in the sense that |
| Boost.Flyweight internal machinery funnels the results produced by an |
| element into the following: |
| <ul> |
| <li><code>Tracking::entry_type</code> is a |
| <a href="lambda_expressions.html"><code>Lambda |
| Expression</code></a> accepting two different types named |
| <code>Value</code> and <code>Key</code> such that |
| <code>Value</code> is implicitly convertible to |
| <code>const Key&</code>. The expression is expected |
| to return |
| a type implicitly convertible to both <code>const Value&</code> |
| and <code>const Key&</code>. |
| <code>Tracking::entry_type</code> corresponds to the actual |
| type of the entries stored into the |
| <a href="configuration.html#factory_types">flyweight factory</a>: |
| by allowing the tracking policy to take part on the definition |
| of this type it is possible for the policy to add internal |
| tracking information to the entry data in case this is needed. |
| If no additional information is required, |
| the tracking policy can simply return <code>Value</code> as its |
| <code>Tracking::entry_type</code> type. |
| </li> |
| <li> |
| The binary <a href="lambda_expressions.html"><code>Lambda |
| Expression</code></a> <code>Tracking::handle_type</code> is invoked |
| with types <code>InternalHandle</code> and <code>TrackingHandler</code> |
| to produce a type <code>Handle</code>, which will be used as the handle |
| type of the flyweight factory. |
| <a href="../reference/tracking.html#preliminary"><code>TrackingHandler</code></a> |
| is passed as a template argument to <code>Tracking::handle_type</code> |
| to offer functionality supporting the implementation of the tracking |
| code. |
| </li> |
| </ul> |
| So, in order to define the factory of some instantiation |
| <code>fw_t</code> of <code>flyweight</code>, <code>Tracking::entry_type</code> |
| is invoked with an internal type <code>Value</code> implicitly convertible |
| to <code>const fw_t::key_type&</code> to obtain the entry type for the factory, |
| which must be convertible to both <code>const Value&</code> and |
| <code>const fw_t::key_type&</code>. |
| Then, <code>Tracking::handle_type</code> is fed an internal handle |
| type and a tracking policy helper to produce the factory handle type. |
| The observant reader might have detected an apparent circularity: |
| <code>Tracking::handle_type</code> produces the handle type of |
| the flyweight factory, and at the same time is passed a tracking helper |
| that grants access to the factory being defined! |
| The solution to this riddle comes from the realization of the fact that |
| <code>TrackingHandler</code> is an <i>incomplete |
| type</i> by the time it is passed to <code>Tracking::handle_type</code>: |
| only when <code>Handle</code> is instantiated at a later stage will this |
| type be complete. |
| </p> |
| |
| <p> |
| In order for a tracking policy to be passed to <code>flyweight</code>, |
| it must be tagged much in the same way as the rest of specifiers. |
| </p> |
| |
| <blockquote><pre> |
| <span class=comment>// Alternatives for tagging a tracking policy</span> |
| |
| <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>tracking_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> |
| |
| <span class=comment>// 1: Have the policy derive from tracking_marker</span> |
| |
| <span class=keyword>struct</span> <span class=identifier>custom_tracking</span><span class=special>:</span> <span class=identifier><b>tracking_marker</b></span> |
| <span class=special>{</span> |
| <span class=special>...</span> |
| <span class=special>};</span> |
| |
| <span class=comment>// 2: Specialize the is_tracking class template</span> |
| |
| <span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> |
| <span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> |
| |
| <span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_tracking</span><span class=special><</span><span class=identifier>custom_tracking</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>true_</span><span class=special>{};</span> |
| |
| <span class=special>}}</span> |
| |
| <span class=comment>// 3: use the tracking<> wrapper when passing the policy |
| // to flyweight</span> |
| |
| <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>tracking</b></span><span class=special><</span><span class=identifier>custom_tracking</span><span class=special>></span> |
| <span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> |
| </pre></blockquote> |
| |
| <p> |
| Tracking policies are their own specifiers, that is, they are provided directly |
| as template arguments to the <code>flyweight</code> class template. |
| </p> |
| |
| <hr> |
| |
| <div class="prev_link"><a href="configuration.html"><img src="../prev.gif" alt="configuring Boost.Flyweight" border="0"><br> |
| Configuring Boost.Flyweight |
| </a></div> |
| <div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br> |
| Boost.Flyweight tutorial |
| </a></div> |
| <div class="next_link"><a href="technical.html"><img src="../next.gif" alt="technical issues" border="0"><br> |
| Technical issues |
| </a></div><br clear="all" style="clear: all;"> |
| |
| <br> |
| |
| <p>Revised December 2nd 2008</p> |
| |
| <p>© Copyright 2006-2008 Joaquín M López Muñoz. |
| Distributed under the Boost Software |
| License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> |
| LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> |
| http://www.boost.org/LICENSE_1_0.txt</a>) |
| </p> |
| |
| </body> |
| </html> |