123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562 |
- <!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#example8">Example 8</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 September 1st 2014</p>
- <p>© Copyright 2006-2014 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>
|