563 lines
34 KiB
HTML
563 lines
34 KiB
HTML
<!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>
|