added flyweight from trunk

[SVN r50320]
This commit is contained in:
Joaquín M López Muñoz
2008-12-18 22:18:11 +00:00
commit a5665e6ee1
114 changed files with 11726 additions and 0 deletions

96
.gitattributes vendored Normal file
View File

@@ -0,0 +1,96 @@
* text=auto !eol svneol=native#text/plain
*.gitattributes text svneol=native#text/plain
# Scriptish formats
*.bat text svneol=native#text/plain
*.bsh text svneol=native#text/x-beanshell
*.cgi text svneol=native#text/plain
*.cmd text svneol=native#text/plain
*.js text svneol=native#text/javascript
*.php text svneol=native#text/x-php
*.pl text svneol=native#text/x-perl
*.pm text svneol=native#text/x-perl
*.py text svneol=native#text/x-python
*.sh eol=lf svneol=LF#text/x-sh
configure eol=lf svneol=LF#text/x-sh
# Image formats
*.bmp binary svneol=unset#image/bmp
*.gif binary svneol=unset#image/gif
*.ico binary svneol=unset#image/ico
*.jpeg binary svneol=unset#image/jpeg
*.jpg binary svneol=unset#image/jpeg
*.png binary svneol=unset#image/png
*.tif binary svneol=unset#image/tiff
*.tiff binary svneol=unset#image/tiff
*.svg text svneol=native#image/svg%2Bxml
# Data formats
*.pdf binary svneol=unset#application/pdf
*.avi binary svneol=unset#video/avi
*.doc binary svneol=unset#application/msword
*.dsp text svneol=crlf#text/plain
*.dsw text svneol=crlf#text/plain
*.eps binary svneol=unset#application/postscript
*.gz binary svneol=unset#application/gzip
*.mov binary svneol=unset#video/quicktime
*.mp3 binary svneol=unset#audio/mpeg
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
*.ps binary svneol=unset#application/postscript
*.psd binary svneol=unset#application/photoshop
*.rdf binary svneol=unset#text/rdf
*.rss text svneol=unset#text/xml
*.rtf binary svneol=unset#text/rtf
*.sln text svneol=native#text/plain
*.swf binary svneol=unset#application/x-shockwave-flash
*.tgz binary svneol=unset#application/gzip
*.vcproj text svneol=native#text/xml
*.vcxproj text svneol=native#text/xml
*.vsprops text svneol=native#text/xml
*.wav binary svneol=unset#audio/wav
*.xls binary svneol=unset#application/vnd.ms-excel
*.zip binary svneol=unset#application/zip
# Text formats
.htaccess text svneol=native#text/plain
*.bbk text svneol=native#text/xml
*.cmake text svneol=native#text/plain
*.css text svneol=native#text/css
*.dtd text svneol=native#text/xml
*.htm text svneol=native#text/html
*.html text svneol=native#text/html
*.ini text svneol=native#text/plain
*.log text svneol=native#text/plain
*.mak text svneol=native#text/plain
*.qbk text svneol=native#text/plain
*.rst text svneol=native#text/plain
*.sql text svneol=native#text/x-sql
*.txt text svneol=native#text/plain
*.xhtml text svneol=native#text/xhtml%2Bxml
*.xml text svneol=native#text/xml
*.xsd text svneol=native#text/xml
*.xsl text svneol=native#text/xml
*.xslt text svneol=native#text/xml
*.xul text svneol=native#text/xul
*.yml text svneol=native#text/plain
boost-no-inspect text svneol=native#text/plain
CHANGES text svneol=native#text/plain
COPYING text svneol=native#text/plain
INSTALL text svneol=native#text/plain
Jamfile text svneol=native#text/plain
Jamroot text svneol=native#text/plain
Jamfile.v2 text svneol=native#text/plain
Jamrules text svneol=native#text/plain
Makefile* text svneol=native#text/plain
README text svneol=native#text/plain
TODO text svneol=native#text/plain
# Code formats
*.c text svneol=native#text/plain
*.cpp text svneol=native#text/plain
*.h text svneol=native#text/plain
*.hpp text svneol=native#text/plain
*.ipp text svneol=native#text/plain
*.tpp text svneol=native#text/plain
*.jam text svneol=native#text/plain
*.java text svneol=native#text/plain

88
doc/acknowledgements.html Normal file
View File

@@ -0,0 +1,88 @@
<!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 - Acknowledgements</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="release_notes.html">
<link rel="up" href="index.html">
</head>
<body>
<h1><img src="../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Acknowledgements</h1>
<div class="prev_link"><a href="release_notes.html"><img src="prev.gif" alt="release notes" border="0"><br>
Release notes
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link">
</div><br clear="all" style="clear: all;">
<hr>
<p>
The following people have provided valuable feedback and suggestions during the
development of the library: Ion Gazta&ntilde;aga, Janek Kozicki, Tobias Schwinger,
Pavel Vo&#382;en&iacute;lek. Simon Atanasyan contributed a workaround for a
problem with Sun Studio compilers. Rosa Bern&aacute;rdez has proofread the
documentation from the first drafts up to its present form.
</p>
<p>
The acceptance review of Boost.Flyweight took place between January 21st
and February 3rd 2008. Many thanks to Ion Gazta&ntilde;aga, the stalwart review manager,
and to all the reviewers: Alberto Ganesh Barbati, Tim Blechmann,
Vicente Juan Botet Escrib&aacute;, Mat&iacute;as Capeletto, Neil Hunt, Marcus Lindblom,
John Reid, David Sankel, Kevin Sopp, John Torjo, Markus Werle. Alberto identified
important limitations of the initial design, which led to the
introduction of <a href="tutorial/key_value.html">key-value flyweights</a>.
</p>
<p>
Boost.Flyweight relies on the
<a href="../../mpl/doc/index.html">Boost MPL Library</a> from
Aleksey Gurtovoy. The
<a href="tutorial/configuration.html#free_order_template">free-order template
parameter interface</a> offered by the library has been implemented
with the <a href="../../parameter/doc/html/index.html">Boost Parameter
Library</a> from David Abrahams and Daniel Wallin. Ion Gazta&ntilde;aga's
<a href="../../interprocess/index.html">Boost Interprocess Library</a>
is the core element behind the
<a href="tutorial/configuration.html#intermodule_holder"><code>intermodule_holder</code></a>
component.
</p>
<p>
This work is dedicated to Jorge L&oacute;pez, in the hope that past
dire straits gentler oceans will lie.
</p>
<hr>
<div class="prev_link"><a href="release_notes.html"><img src="prev.gif" alt="release notes" border="0"><br>
Release notes
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link">
</div><br clear="all" style="clear: all;">
<br>
<p>Revised December 10th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

258
doc/examples.html Normal file
View File

@@ -0,0 +1,258 @@
<!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 - Examples</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="performance.html">
<link rel="up" href="index.html">
<link rel="next" href="tests.html">
</head>
<body>
<h1><img src="../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Examples</h1>
<div class="prev_link"><a href="performance.html"><img src="prev.gif" alt="performance" border="0"><br>
Performance
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="tests.html"><img src="next.gif" alt="tests" border="0"><br>
Tests
</a></div><br clear="all" style="clear: all;">
<br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#example1">Example 1: basic usage</a></li>
<li><a href="#example2">Example 2: key-value flyweights</a></li>
<li><a href="#example3">Example 3: flyweights and the composite pattern</a></li>
<li><a href="#example4">Example 4: formatted text processing</a></li>
<li><a href="#example5">Example 5: flyweight-based memoization</a></li>
<li><a href="#example6">Example 6: performance comparison</a></li>
<li><a href="#example7">Example 7: custom factory</a></li>
</ul>
<h2><a name="example1">Example 1: basic usage</a></h2>
<p>
See <a href="../example/basic.cpp">source code</a>.
</p>
<p>
Dummy program showing the basic capabilities of <code>flyweight</code>
explained at the <a href="tutorial/basics.html">tutorial</a>.
</p>
<h2><a name="example2">Example 2: key-value flyweights</a></h2>
<p>
See <a href="../example/key_value.cpp">source code</a>.
</p>
<p>
The program simulates the scenario described at the tutorial section on
<a href="tutorial/key_value.html">key-value flyweights</a>: The class
<code>texture</code> manages some texture rendering data stored in
a file whose location is given at construction time. The program
handles large quantities of objects of this class by encapsulating
them into key-value flyweights keyed by filename. Observe how the
execution of the program results in no extra constructions or copies
of objects of type <code>texture</code> except those absolutely
necessary.
</p>
<h2><a name="example3">Example 3: flyweights and the composite pattern</a></h2>
<p>
See <a href="../example/composite.cpp">source code</a>.
</p>
<p>
The <a href="http://c2.com/cgi/wiki?CompositePattern"><i>composite
design pattern</i></a> revolves about the idea that a tree data structure
can be easily constructed and manipulated by defining the tree node type
polymorphically so that either is a leaf node or else contains a list of
pointers to their child nodes.
This way, a tree is the exact same entity as its root node, which allows
for very simple recursive tree-handling algorithms. Large composite trees
having a high degree of duplication of nodes and subtrees (as for instance
those generated when parsing a computer program) are a natural fit for the
flyweight idiom: simply turning the node type into a flyweight
automatically deals with duplication at the node and subtree level.
</p>
<p>
The example program parses Lisp-like lists of the form
<code>(a<sub>1</sub> ... a<sub><i>n</i></sub>)</code> where each
<code>a<sub>i</sub></code> is a terminal string or a list. The parsed
data structure is a composite type defined using Boost.Flyweight in conjunction
with the recursive facilities of
<a href="../../variant/index.html">Boost.Variant</a>. So, given the list
</p>
<blockquote><pre>
(= (tan (+ x y))(/ (+ (tan x)(tan y))(- 1 (* (tan x)(tan y)))))
</pre></blockquote>
<p>
the resulting data structure implicitly detects the duplicated
occurrences of <code>+</code>, <code>x</code>, <code>y</code>,
<code>tan</code>, <code>(tan x)</code> and <code>(tan y)</code>.
</p>
<h2><a name="example4">Example 4: formatted text processing</a></h2>
<p>
See <a href="../example/html.cpp">source code</a>.
</p>
<p>
A classic example of application of the flyweight pattern is that of a
text processor which handles characters with rich formatting information,
like font type, size, color and special options (boldness, italics, etc.)
Coding the formatting information of each character takes considerable
space, but, given the high degree of repetition typical in a document,
maintaining formatted characters as flyweight objects drastically reduces
memory consumption.
</p>
<p>
The example program parses, manipulates and stores HTML documents following
flyweight-based representation techniques. Given the hierarchical nature
of HTML markup, a crude approximation to the formatting options of a given
character is just to equate them with the stack of tag contexts to which
the character belongs, as the figure shows.
</p>
<p align="center">
<img src="html.png"
alt="formatting contexts of characters in an HTML document"
width="320" height="275"><br>
<b>Fig. 1: Formatting contexts of characters in an HTML document.</b>
</p>
<p>
HTML documents are then parsed as arrays of (character, format)
pairs, where the format is the tag context as described above. The very high
degree of redundancy in formatting information is taken care of by the
use of Boost.Flyweight. This character-based representation makes it
easy to manipulate the document: transposition and elimination of
portions of text are trivial operations. As an example, the program
reverses the text occupying the central portion of the document.
Saving the result in HTML reduces to traversing the array of formatted
characters and emitting opening/closing HTML tags as the context of adjacent
characters varies.
</p>
<p>
For the sake of brevity, the HTML parsing capabilities of this program
are coarse: for instance, elements without end-tag (like &lt;BR&gt;), character
enconding and HTML entities (e.g. "&amp;copy;" for &copy;) are not properly
handled. Improving the parsing code is left as an exercise to the reader.
</p>
<h2><a name="example5">Example 5: flyweight-based memoization</a></h2>
<p>
See <a href="../example/fibonacci.cpp">source code</a>.
</p>
<p>
<a href="http://en.wikipedia.org/wiki/Memoization">Memoization</a>
is an optimization technique consisting in caching
the results of a computation for later reuse; this can dramatically
improve performance when calculating recursive numerical functions,
for instance. <a href="tutorial/key_value.html">Key-value flyweights</a>
can be used to implement memoization for a numerical function <i>f</i>
by modeling a memoized invocation of the function as a value of
type <code>flyweight&lt;key_value&lt;int,compute_f&gt; &gt;</code>, where
<code>compute_f</code> is a type that does the computation of
<i>f</i>(<i>n</i>) at its <code>compute_f::compute_f(int)</code> constructor.
For instance, the <a href="http://mathworld.wolfram.com/FibonacciNumber.html">Fibonacci
numbers</a> can be computed with memoization like this:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>key_value</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>,</span><span class=identifier>compute_fibonacci</span><span class=special>&gt;,</span><span class=identifier>no_tracking</span><span class=special>&gt;</span> <span class=identifier>fibonacci</span><span class=special>;</span>
<span class=keyword>struct</span> <span class=identifier>compute_fibonacci</span>
<span class=special>{</span>
<span class=identifier>compute_fibonacci</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>n</span><span class=special>):</span>
<span class=identifier>result</span><span class=special>(</span><span class=identifier>n</span><span class=special>==</span><span class=number>0</span><span class=special>?</span><span class=number>0</span><span class=special>:</span><span class=identifier>n</span><span class=special>==</span><span class=number>1</span><span class=special>?</span><span class=number>1</span><span class=special>:</span><span class=identifier>fibonacci</span><span class=special>(</span><span class=identifier>n</span><span class=special>-</span><span class=number>2</span><span class=special>).</span><span class=identifier>get</span><span class=special>()+</span><span class=identifier>fibonacci</span><span class=special>(</span><span class=identifier>n</span><span class=special>-</span><span class=number>1</span><span class=special>).</span><span class=identifier>get</span><span class=special>())</span>
<span class=special>{}</span>
<span class=keyword>operator</span> <span class=keyword>int</span><span class=special>()</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>result</span><span class=special>;}</span>
<span class=keyword>int</span> <span class=identifier>result</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
<p>
The <a href="tutorial/configuration.html#no_tracking"><code>no_tracking</code></a>
policy is used so that the memoized computations persist for future
use throughout the program. The provided program develops this example in full.
</p>
<h2><a name="example6">Example 6: performance comparison</a></h2>
<p>
See <a href="../example/perf.cpp">source code</a>.
</p>
<p>
This program measures the time and space performances of a simple
string type against several differently configured <code>flyweight</code>
instantations as used in a conventional task involving parsing a file and
doing some manipulations on the parsed text.
Memory consumption is computed by instrumenting the relevant
components (the string type itself, flyweight factories, etc.) with custom
allocators that keep track of the allocations and deallocations requested.
The program has been used to produce the experimental results given
at the <a href="performance.html#results">performance section</a>.
</p>
<h2><a name="example7">Example 7: custom factory</a></h2>
<p>
See <a href="../example/custom_factory.cpp">source code</a>.
</p>
<p>
The example shows how to write and use a custom factory class. This
"verbose" factory outputs messages tracing the invocations of its public interface
by Boost.Flyweight, so helping the user visualize factory usage patterns.
</p>
<hr>
<div class="prev_link"><a href="performance.html"><img src="prev.gif" alt="performance" border="0"><br>
Performance
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="tests.html"><img src="next.gif" alt="tests" border="0"><br>
Tests
</a></div><br clear="all" style="clear: all;">
<br clear="all" style="clear: all;">
<br>
<p>Revised December 2nd 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

128
doc/future_work.html Normal file
View File

@@ -0,0 +1,128 @@
<!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 - Future work</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="examples.html">
<link rel="prev" href="tests.html">
<link rel="up" href="index.html">
<link rel="next" href="release_notes.html">
</head>
<body>
<h1><img src="../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Future work</h1>
<div class="prev_link"><a href="tests.html"><img src="prev.gif" alt="examples" border="0"><br>
Tests
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="release_notes.html"><img src="next.gif" alt="release notes" border="0"><br>
Release notes
</a></div><br clear="all" style="clear: all;">
<br clear="all" style="clear: all;">
<hr>
<p>
New functionalities can be included into future releases of Boost.Flyweight
to meet the demands of users and to leverage upcoming C++0x features
and new Boost libraries. The following is a list of candidate additions.
</p>
<h2>Contents</h2>
<ul>
<li><a href="#instrospection">Introspection API</a></li>
<li><a href="#perfect_fwd">Perfect forwarding</a></li>
<li><a href="#rw_lock">Read/write locking policy</a></li>
<li><a href="#new_boost_libs">Integration with new Boost libraries</a></li>
</ul>
<h2><a name="instrospection">Introspection API</a></h2>
<p>
Currently there is no way to access the internal components of a
<code>flyweight</code> instantiation (factory, holder, etc.) or even
to know the types of these components. With such an API it would be
possible to instrument and monitor the usage of Boost.Flyweight like in
the following example:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=identifier>fw_type</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>&lt;&lt;</span><span class=string>&quot;factory used: &quot;</span><span class=special>&lt;&lt;</span><span class=keyword>typeid</span><span class=special>(</span><span class=identifier>fw_type</span><span class=special>::</span><span class=identifier>factory_type</span><span class=special>).</span><span class=identifier>name</span><span class=special>()&lt;&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>&lt;&lt;</span><span class=string>&quot;values stored: &quot;</span><span class=special>&lt;&lt;</span><span class=identifier>fw_type</span><span class=special>::</span><span class=identifier>factory</span><span class=special>().</span><span class=identifier>size</span><span class=special>()&lt;&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span>
</pre></blockquote>
<h2><a name="perfect_fwd">Perfect forwarding</a></h2>
<p>
When constructing a <code>flyweight&lt;T&gt; object</code>, some spurious copies
of objects of type <code>T</code> are incurred in the process of moving the value
into the internal factory. So-called <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html#Perfect_Forwarding"><i>perfect
forwarding</i></a>, i.e. performing the move without generating temporary
copies, will be solved in an optimum manner by a new
type of <i>rvalue references</i> to be included in the next revision of the
C++ standard. Boost.Flyweight will take advantage of this feature as
compilers begin to provide it.
</p>
<h2><a name="rw_lock">Read/write locking policy</a></h2>
<p>
The nature of the flyweight pattern implies that most accesses
to the internal flyweight factory do not cause new insertions and can
thus be considered read-only. This hints at the convenience of using
a locking policy based on read/write locks such as those provided by
<a href="../../../doc/html/thread/synchronization.html#thread.synchronization.mutex_concepts.shared_lockable">Boost.Thread</a>.
Implementing a locking policy will also require extending the
<a href="reference/factories.html#factory"><code>Factory</code></a> concept
to allow for pure lookup operations. Tim Blechmann has provided a
preliminary <a href="http://lists.boost.org/Archives/boost/2008/07/139414.php">implementation</a>
of this idea. Before committing to this library extension it is
necessary to do a profiling study to determine whether read/write
locking actually improves performance.
</p>
<h2><a name="new_boost_libs">Integration with new Boost libraries</a></h2>
<p>
Recently accepted Boost libraries like
<a href="http://lists.boost.org/boost-announce/2007/12/0149.php">Boost.Functional/Forward</a>
and <a href="http://lists.boost.org/boost-announce/2007/12/0157.php">Boost.Functional/Factory</a>
might be used in the future to replace some internal machinery of
Boost.Flyweight.
</p>
<hr>
<div class="prev_link"><a href="tests.html"><img src="prev.gif" alt="examples" border="0"><br>
Tests
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="release_notes.html"><img src="next.gif" alt="release notes" border="0"><br>
Release notes
</a></div><br clear="all" style="clear: all;">
<br clear="all" style="clear: all;">
<br>
<p>Revised September 1st 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

BIN
doc/html.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

82
doc/index.html Normal file
View File

@@ -0,0 +1,82 @@
<!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 - Index</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="next" href="tutorial/index.html">
</head>
<body>
<h1><img src="../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost Flyweight Library</h1>
<div class="prev_link"></div>
<div class="up_link"></div>
<div class="next_link"><a href="tutorial/index.html"><img src="next.gif" alt="tutorial" border="0"><br>
Tutorial
</a></div><br clear="all" style="clear: all;">
<hr>
<p>
Flyweights are small-sized handle classes granting constant access to shared
common data, thus allowing for the management of large amounts of entities
within reasonable memory limits. Boost.Flyweight makes it easy to use this
common programming idiom by providing the class template
<code>flyweight&lt;T&gt;</code>, which acts as a drop-in replacement for
<code>const T</code>.
</p>
<p>
Learning to use Boost.Flyweight can be accomplished in a matter of minutes.
When special needs arise, however, an extensive customization interface
is provided which allows the user to control and extend the following aspects:
<ul>
<li>Type tagging for separation of domains using the same basic
flyweight types.</li>
<li>Specification and parameterization of the so-called flyweight
factory.</li>
<li>Control of the factory instantiation procedure.</li>
<li>Specification of the internal synchronization mechanisms.</li>
<li>Flyweight tracking, allowing for the disposal of stored
values when no longer referenced by any flyweight object.</li>
</ul>
</p>
<h2>Contents</h2>
<ul>
<li><a href="tutorial/index.html">Tutorial</a></li>
<li><a href="reference/index.html">Reference</a></li>
<li><a href="performance.html">Performance</a></li>
<li><a href="examples.html">Examples</a></li>
<li><a href="tests.html">Tests</a></li>
<li><a href="future_work.html">Future work</a></li>
<li><a href="release_notes.html">Release notes</a></li>
<li><a href="acknowledgements.html">Acknowledgements</a></li>
</ul>
<hr>
<div class="prev_link"></div>
<div class="up_link"></div>
<div class="next_link"><a href="tutorial/index.html"><img src="next.gif" alt="tutorial" border="0"><br>
Tutorial
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised September 3rd 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

BIN
doc/memory.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
doc/memory_gcc_344.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
doc/memory_msvc_80.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
doc/next.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

472
doc/performance.html Normal file
View File

@@ -0,0 +1,472 @@
<!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 - Performance</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="reference/tracking.html">
<link rel="up" href="index.html">
<link rel="next" href="examples.html">
</head>
<body>
<h1><img src="../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Performance</h1>
<div class="prev_link"><a href="reference/tracking.html"><img src="prev.gif" alt="tracking policies" border="0"><br>
Tracking policies
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="examples.html"><img src="next.gif" alt="examples" border="0"><br>
Examples
</a></div><br clear="all" style="clear: all;">
<br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#memory">Memory consumption</a>
<ul>
<li><a href="#flyweight_size">Flyweight size</a></li>
<li><a href="#entry_size">Entry size</a></li>
<li><a href="#overall_memory">Overall memory consumption</a></li>
</ul>
</li>
<li><a href="#time">Time efficiency</a>
<ul>
<li><a href="#initialization">Initialization</a></li>
<li><a href="#assignment">Assignment</a></li>
<li><a href="#equality_comparison">Equality comparison</a></li>
<li><a href="#value_access">Value access</a></li>
</ul>
</li>
<li><a href="#results">Experimental results</a>
<ul>
<li><a href="#msvc_80">Microsoft Visual C++ 8.0</a>
<ul>
<li><a href="#msvc_80_memory">Memory</a></li>
<li><a href="#msvc_80_time">Execution time</a></li>
</ul>
</li>
<li><a href="#gcc_344">GCC 3.4.4</a>
<ul>
<li><a href="#gcc_344_memory">Memory</a></li>
<li><a href="#gcc_344_time">Execution time</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#conclusions">Conclusions</a></li>
</ul>
<h2><a name="intro">Introduction</a></h2>
<p>
We show how to estimate the memory reduction obtained by the usage of
Boost.Flyweight in a particular scenario and study the impact on the execution
time for the different functional areas of <code>flyweight</code>.
Some experimental results are provided.
</p>
<h2><a name="memory">Memory consumption</a></h2>
<p>
As we saw in the <a href="tutorial/index.html#rationale">tutorial rationale</a>,
the flyweight pattern is based on two types of objects:
<ul>
<li>The flyweight objects proper, which have very small size, typically
that of a pointer.
</li>
<li>The shared values, which are stored as internal <i>entries</i> into the
flyweight factory.
</li>
</ul>
The overall memory consumption is then a function of the size of the
flyweight objects, the size of the entry objects and the degree of
value redundancy.
</p>
<h3><a name="flyweight_size">Flyweight size</a></h3>
<p>
The only data member of a <code>flyweight</code> object is a so-called
<i>handle</i>, an opaque object of small size provided by the internal
flyweight factory to refer to the entries it stores. For the default
<a href="tutorial/configuration.html#hashed_factory"><code>hashed_factory</code></a>,
this handle is merely a pointer, so <code>sizeof(flyweight&lt;T&gt;)=sizeof(void*)</code>,
4 bytes in typical 32-bit architectures.
For other types of factories, the handle is an iterator to an internal
container used in the implementation of the factory: again, its size
is typically that of a pointer.
</p>
<h3><a name="entry_size">Entry size</a></h3>
<p>
The entries stored in the factory associated to <code>flyweight&lt;T,...&gt;</code>
need not only hold a value of <code>T</code>, but also contain additional
information related to the internal implementation of
<code>flyweight&lt;T,...&gt;</code>:
</p>
<blockquote>
<i>entry</i> = <code>sizeof(T)</code> + <i>overhead</i>.
</blockquote>
<p>
For the current implementation of Boost.Flyweight, the following aspects
contribute to <i>overhead</i>:
<ul>
<li>Usage of <a href="tutorial/key_value.html">key-value flyweights</a>.</li>
<li>Internal overhead of the <a href="tutorial/configuration.html#factories">factory</a>
container.
</li>
<li>Bookkeeping information associated to the
<a href="tutorial/configuration.html#tracking">tracking mechanism</a>.
</li>
</ul>
The table summarizes the separate contributions to <i>overhead</i> introduced
by the different components taking part of the definition of
a <code>flyweight</code> instantiation. Values are given in <i>words</i>,
i.e. the size of a pointer, which is 4 bytes in a typical 32-bit architecture.
Alignment may introduce additional overhead.
</p>
<p align="center">
<table cellspacing="0">
<caption><b>Entry overhead of the components of Boost.Flyweight.</b></caption>
<tr>
<th align="center"colspan="2">component</th>
<th align="center">overhead (words)</th>
</tr>
<tr>
<td align="center" rowspan="2">&nbsp;&nbsp;<a href="tutorial/key_value.html#key_value"><code>key_value</code></a>&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;with <a href="tutorial/key_value.html#key_extractor">key extractor</a>&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;1<sup>(1)</sup>&nbsp;&nbsp;</td>
</tr>
<tr>
<td align="center">&nbsp;&nbsp;without <a href="tutorial/key_value.html#key_extractor">key extractor</a>&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;1 + <code>sizeof(Key)&nbsp;&nbsp;</td>
</tr>
<tr class="odd_tr">
<td align="center" rowspan="3">&nbsp;&nbsp;factory&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;<a href="tutorial/configuration.html#hashed_factory"><code>hashed_factory</code></a>&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;~2.5&nbsp;&nbsp;</td>
</tr>
<tr class="odd_tr">
<td align="center">&nbsp;&nbsp;<a href="tutorial/configuration.html#set_factory"><code>set_factory</code></a>&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;4<sup>(2)</sup>&nbsp;&nbsp;</td>
</tr>
<tr class="odd_tr">
<td align="center">&nbsp;&nbsp;<a href="tutorial/configuration.html#assoc_container_factory"><code>assoc_container_factory</code></a>&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;depends on the container used&nbsp;&nbsp;</td>
</tr>
<tr>
<td align="center" rowspan="2">&nbsp;&nbsp;tracking mechanism&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;<a href="tutorial/configuration.html#refcounted"><code>refcounted</code></a>&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;1<sup>(3)</sup>&nbsp;&nbsp;</td>
</tr>
<tr>
<td align="center">&nbsp;&nbsp;<a href="tutorial/configuration.html#no_tracking"><code>no_tracking</code></a>&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;0&nbsp;&nbsp;</td>
</tr>
</table>
<sup>(1)</sup> <small>Assuming that <code>sizeof(Key)&lt;=sizeof(Value)</code>.</small><br>
<sup>(2)</sup> <small>For some implementations of <code>std::set</code> this overhead reduces to 3.</small><br>
<sup>(3)</sup> <small>In some platforms this value can be 2.</small>
</p>
<p>
For instance, for the default configuration parameters of <code>flyweight</code>,
<i>overhead</i> is typically 2.5(<code>hashed_factory</code>) + 1(<code>refcounted</code>)
= 3 words.
</p>
<h3><a name="overall_memory">Overall memory consumption</a></h3>
<p>
Consider a scenario where there are <i>N</i> different objects of type <code>T</code>
jointly taking <i>M</i> different values. The objects consume then
<i>S</i> = <i>N</i>&middot;<i>T</i> bytes, where <i>T</i> is defined as the
average size of <code>T</code> (<code>sizeof(T)</code> plus dynamic
memory allocated by <code>T</code> objects).
If we now replace <code>T</code> by some instantiation
<code>flyweight&lt;T,...&gt;</code>, the resulting memory consumption
will be
</p>
<blockquote>
<i>S<sub>F</sub></i> =
<i>N</i>&middot;<i>P</i> + <i>M</i>&middot;(<i>T</i> + <i>overhead</i>),
</blockquote>
<p>
where <i>P</i> is <code>sizeof(flyweight&lt;T,...&gt;)</code>, typically
equal to <code>sizeof(void*)</code>, as seen <a href="#flyweight_size">before</a>.
The ratio <i>S<sub>F</sub></i> / <i>S</i> is then
</p>
<blockquote>
<i>S<sub>F</sub></i> / <i>S</i> =
(<i>P</i> / <i>T</i>)+ (<i>M</i> / <i>N</i>)(1 + <i>overhead</i> / <i>T</i>).
</blockquote>
<p>
<i>S<sub>F</sub></i> / <i>S</i> tends to its minimum, <i>P</i> / <i>T</i>,
as <i>M</i> / <i>N</i> tends to 0, i.e. when the degree of value redundancy
among <code>T</code> objects grows higher. On the other hand, the worst possible case
<i>S<sub>F</sub></i> / <i>S</i> = 1 + (<i>P</i> + <i>overhead</i>) / <i>T</i>
happens when <i>M</i> / <i>N</i> = 1, that is, if there is no value redundancy at all; in this situation there is
no point in applying the flyweight pattern in the first place.
</p>
<p align="center">
<img src="memory.png" alt="relative memory consumption of Boost.Flyweight as a function of value diversity"
width="446" height="411"><br>
<b>Fig. 1: Relative memory consumption of Boost.Flyweight as a function of value diversity.</b>
</p>
<h2>
<a name="time">Time efficiency</a>
</h2>
<p>
The introduction of the flyweight pattern involves an extra level of indirection
that, in general, results in some execution overhead when accessing the values. On
the other hand, manipulation of flyweight objects is considerably faster than
moving around the heavy values they stand for. We analyze qualitatively the
execution overheads or improvements associated to the different usage contexts
of Boost.Flyweight.
</p>
<h3><a name="initialization">Initialization</a></h3>
<p>
As compared with the initialization an object of type <code>T</code>, constructing
a <code>flyweight&lt;T&gt;</code> performs important extra work like looking
up the value in the flyweight factory and inserting it if it is not present.
So, construction of flyweights (other than copy construction, which is
cheap), is expected to be noticeably slower than the construction of the
underlying type <code>T</code>. Much of the time spent at constructing
the associated <code>T</code> value proper can be saved, however, by
using <a href="tutorial/key_value.html">key-value flyweights</a>.
</p>
<h3><a name="assignment">Assignment</a></h3>
<p>
Assignment of flyweight objects is extremely fast, as it only involves
assigning an internal handle type used to refer to the shared value. Moreover,
assignment of <code>flyweight</code> objects never throws. Assignment time
is influenced by the type of <a href="tutorial/configuration.html#tracking">tracking
policy</a> used; in this regard,
<a href="tutorial/configuration.html#no_tracking"><code>no_tracking</code></a>
is the fastest option.
</p>
<h3><a name="equality_comparison">Equality comparison</a></h3>
<p>
Comparing two <code>flyweight</code> objects for equality reduces to
checking that the <i>addresses</i> of the values they are associated to
are equal; in general, this operation is much faster than comparing the
underlying values. This aspect is of particular relevance when the flyweight
objects stand for complex values like those arising in the application of
the <a href="examples.html#example3"><i>composite pattern</i></a>.
</p>
<h3><a name="value_access">Value access</a></h3>
<p>
The conversion from <code>flyweight&lt;T&gt;</code> to <code>const T&amp;</code>
relies on a level of indirection relating the flyweight objects to the
values they are associated to; so, value access is expected to be slower
when using Boost.Flyweight as compared to using the associated values
directly. This overhead, however, can be masked by an indirect improvement
resulting from locality and cache effects: as the set of different <code>T</code>
values handled by an instantiation of <code>flyweight&lt;T&gt;</code> is
generally much smaller than the equivalent family of <code>T</code> objects
when Boost.Flyweight is not used, active values can fit better
into the processor cache.
</p>
<h2><a name="results">Experimental results</a></h2>
<p>
A <a href="examples.html#example6">profiling program</a> was devised to test
the space and time efficiency of different instantiations of <code>flyweight</code>
against a base situation not using Boost.Flyweight. The profiled scenarios are:
<ol>
<li><code>std::string</code>.</li>
<li><code>flyweight&lt;std::string&gt;</code> with default configuration aspects
(<a href="tutorial/configuration.html#hashed_factory"><code>hashed_factory</code></a>,
<a href="tutorial/configuration.html#refcounted"><code>refcounted</code></a> tracking,
<a href="tutorial/configuration.html#simple_locking"><code>simple_locking</code></a>).
</li>
<li><code>flyweight&lt;std::string,<a href="tutorial/configuration.html#no_tracking"><code>no_tracking</code></a>&gt;</code>.</li>
<li><code>flyweight&lt;std::string,<a href="tutorial/configuration.html#set_factory"><code>set_factory</code></a>&gt;</code>.</li>
<li><code>flyweight&lt;std::string,<a href="tutorial/configuration.html#set_factory"><code>set_factory</code></a>,<a href="tutorial/configuration.html#no_tracking"><code>no_tracking</code></a>&gt;</code>.</li>
</ol>
</p>
<p>
Actually the types tested are not exactly those listed above, but instrumented
versions that keep track of the allocated memory for profiling purposes.
The program parses a text file into an array of words and then perform various
manipulations involving the different context usages of Boost.Flyweight discussed
<a href="#time">previously</a>. As our text file we have used the
<a href="http://www.gutenberg.org/dirs/etext99/2donq10.txt">plain text</a>
version of Project Gutenberg edition of <a href="http://www.gutenberg.org/etext/2000"><i>Don
Quijote</i></a> (2.04 MB).
</p>
<h3><a name="msvc_80">Microsoft Visual C++ 8.0</a></h3>
<p>
The program was built with default release settings and <code>_SECURE_SCL=0</code>.
Tests were run under Windows XP in a machine equipped with an Intel Core 2 Duo T5500
processor and 1 GB of RAM.
</p>
<h4><a name="msvc_80_memory">Memory</a></h4>
<p align="center">
<img src="memory_msvc_80.png" alt="memory consumption (MB), MSVC++ 8.0"
width="798" height="322"><br>
<b>Fig. 2: Memory consumption, MSVC++ 8.0. Values in MB.</b>
</p>
<p>
The results show the memory consumption figures for the different profiled
scenarios.
The standard library implementation of MSVC++ 8.0 features the so-called
small buffer optimization for strings, by which <code>std::string</code>
objects hold a small buffer that can be used when the string is short,
thus avoding dynamic allocations. This results in <code>sizeof(std::string)</code>
being quite high, 28 bytes. In our particular test strings are almost always
held in the small buffer, so the minimum <a href="#overall_memory"><i>S<sub>F</sub></i> / <i>S</i></a>
achievable is 4/28 = 14.3%, which is quite close to the experimental
results, given that the memory devoted to storage of shared values
is residual (around 3% of total memory) due to the high word redundancy
of the text source.
</p>
<h4><a name="msvc_80_time">Execution time</a></h4>
<p align="center">
<img src="time_msvc_80.png" alt="execution time (s), MSVC++ 8.0"
width="820" height="324"><br>
<b>Fig. 3: Execution time, MSVC++ 8.0. Values in seconds.</b>
</p>
<p>
The figure displays execution times for the profiled scenarios in different
usage contexts. In accordance with our previous
<a href="#time">qualitative analysis</a>, initialization of <code>flyweight</code>s
carries an important overhead with respect to the base case scenario (between 10% and 40%
of additional execution time), while the other usage contexts
(assignment, equality comparison and value access) have performance gains,
with speedup factors of up to 14 in some cases. The use of a
<a href="tutorial/configuration.html#refcounted"><code>refcounted</code></a>
tracking policy introduces penalties with respect to
<a href="tutorial/configuration.html#no_tracking"><code>no_tracking</code></a>
in initialization and assignment, but has no effect in equality comparison
and value access.
</p>
<h3><a name="gcc_344">GNU GCC 3.4.4</a></h3>
<p>
The Cygwin/MinGW version of the compiler was used, with command options
<code>-ftemplate-depth-128 -O3 -finline-functions -DNDEBUG</code>.
Tests were run under a Cygwin terminal in the same machine as <a href="#msvc_80">before</a>.
</p>
<h4><a name="gcc_344_memory">Memory</a></h4>
<p align="center">
<img src="memory_gcc_344.png" alt="memory consumption (MB), GCC 3.4.4"
width="798" height="322"><br>
<b>Fig. 4: Memory consumption, GCC 3.4.4. Values in MB.</b>
</p>
<p>
The standard library used by GCC 3.4.4 implements <code>std::string</code>
using <a href="http://en.wikipedia.org/wiki/Copy-on-write">copy-on-write</a>
optimization techniques, which leads to very small value redundancy for
some usage patterns. This explains why the memory reduction achieved
by Boost.Flyweight is so poor in this case. Other contexts where assignment
is much less used than direct construction will favor Boost.Flyweight
over plain copy-on-write <code>std::string</code>s.
</p>
<h4><a name="gcc_344_time">Execution time</a></h4>
<p align="center">
<img src="time_gcc_344.png" alt="execution time (s), GCC 3.4.4"
width="820" height="324"><br>
<b>Fig. 5: Execution time, GCC 3.4.4. Values in seconds.</b>
</p>
<p>
Relative performance figures are similar to those obtained for
<a href="#msvc_80_time">MSVC++ 8.0</a>, although some of the
speedups achieved by Boost.Flyweight are higher here (&times;25
in equality comparison and up to &times;100 in assignment when
<a href="tutorial/configuration.html#no_tracking"><code>no_tracking</code></a>
is in effect).
</p>
<h2><a name="conclusions">Conclusions</a></h2>
<p>
The introduction of Boost.Flyweight in application scenarios with very
high value redundancy yields important reductions in memory consumption:
this is especially relevant when data volume approaches the limits of
physical memory in the machine, since Boost.Flyweight can avoid virtual
memory thrashing thus making the application viable. We have shown
how to estimate the achievable reduction in memory consumption from
some basic value statistics and knowledge of the <code>flyweight</code>
configuration aspects being used.
</p>
<p>
Boost.Flyweight can also accelerate execution times in areas other than
object initialization, due to the fastest manipulation of small
flyweight objects and to locality and cache effects arising from the
drastic reduction of the set of allocated values.
</p>
<hr>
<div class="prev_link"><a href="reference/tracking.html"><img src="prev.gif" alt="tracking policies" border="0"><br>
Tracking policies
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="examples.html"><img src="next.gif" alt="examples" border="0"><br>
Examples
</a></div><br clear="all" style="clear: all;">
<br clear="all" style="clear: all;">
<br>
<p>Revised December 2nd 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

BIN
doc/prev.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

View File

@@ -0,0 +1,583 @@
<!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 - Factories reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="tags.html">
<link rel="up" href="index.html">
<link rel="next" href="holders.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight
Factories reference</h1>
<div class="prev_link"><a href="tags.html"><img src="../prev.gif" alt="tags" border="0"><br>
Tags
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="holders.html"><img src="../next.gif" alt="holders" border="0"><br>
Holders
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#factory">Factories and factory specifiers</a></li>
<li><a href="#factory_tag_synopsis">Header
<code>"boost/flyweight/factory_tag.hpp"</code> synopsis</a>
<ul>
<li><a href="#is_factory">Class template <code>is_factory</code></a></li>
<li><a href="#factory_construct">Class template <code>factory</code></a></li>
</ul>
</li>
<li><a href="#hashed_factory_fwd_synopsis">Header
<code>"boost/flyweight/hashed_factory_fwd.hpp"</code> synopsis</a>
</li>
<li><a href="#hashed_factory_synopsis">Header
<code>"boost/flyweight/hashed_factory.hpp"</code> synopsis</a>
<ul>
<li><a href="#hashed_factory_class">Class template <code>hashed_factory_class</code></a></li>
<li><a href="#hashed_factory">Class template <code>hashed_factory</code></a></li>
</ul>
</li>
<li><a href="#set_factory_fwd_synopsis">Header
<code>"boost/flyweight/set_factory_fwd.hpp"</code> synopsis</a>
</li>
<li><a href="#set_factory_synopsis">Header
<code>"boost/flyweight/set_factory.hpp"</code> synopsis</a>
<ul>
<li><a href="#set_factory_class">Class template <code>set_factory_class</code></a></li>
<li><a href="#set_factory">Class template <code>set_factory</code></a></li>
</ul>
</li>
<li><a href="#assoc_container_factory_fwd_synopsis">Header
<code>"boost/flyweight/assoc_container_factory_fwd.hpp"</code> synopsis</a>
</li>
<li><a href="#assoc_container_factory_synopsis">Header
<code>"boost/flyweight/assoc_container_factory.hpp"</code> synopsis</a>
<ul>
<li><a href="#assoc_container_factory_class">Class template <code>assoc_container_factory_class</code></a></li>
<li><a href="#assoc_container_factory">Class template <code>assoc_container_factory</code></a></li>
</ul>
</li>
</ul>
<h2><a name="factory">Factories and factory specifiers</a></h2>
<p>
Given a type <code>Key</code> and an
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
type <code>Entry</code> implicitly convertible to <code>const Key&amp;</code>, a
<i>factory of <code>Entry</code> elements</i> (implicitly associated to
<code>Key</code>) is a
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"><code>Default
Constructible</code></a> entity able to store and retrieve immutable elements of
type <code>Entry</code>. A factory is governed by an associated equivalence
relation defined on <code>Key</code> so that no two
<code>Entry</code> objects convertible to equivalent <code>Key</code>s
can be stored simultaneously in the factory. Different factory types can
use different equivalence relations.
</p>
<p>
In the following table, <code>Factory</code> is a factory of elements
of type <code>Entry</code>, <code>f</code> denotes an object of type <code>Factory</code>,
<code>x</code> is an object of type <code>Entry</code> and <code>h</code> is a
value of <code>Factory::handle_type</code>.
</p>
<p align="center">
<table cellspacing="0">
<caption><b>Factory requirements.</b></caption>
<tr>
<th align="center">expression</th>
<th align="center">return type</th>
<th align="center">assertion/note<br>pre/post-condition</th>
</tr>
<tr>
<td><code>Factory::handle_type</code></td>
<td>handle to elements of type <code>T</code><br>
stored in the factory
</td>
<td><code>handle_type</code> is
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
and its copy and<br>
assignment operations never throw an exception.
</td>
</tr>
<tr class="odd_tr">
<td><code>f.insert(x);</code></td>
<td><code>handle_type</code></td>
<td>Inserts a copy of <code>x</code> if there is no equivalent entry in <code>f</code>;<br>
returns a handle to the inserted or equivalent element.
</td>
</tr>
<tr>
<td><code>f.erase(h);</code></td>
<td><code>void</code></td>
<td>Erases the element associated to <code>h</code>.<br>
This operation does not throw.
</td>
</tr>
<tr class="odd_tr">
<td><code>f.entry(h);</code></td>
<td><code>const Entry&amp;</code></td>
<td>Returns a reference to the element associated to <code>h</code>.<br>
This operation does not throw.
</td>
</tr>
</table>
</p>
<p>
Additionally to the basic thread safety guarantee which is implicitly assumed
for most classes including the majority of components of the
C++ standard library, it is required that the member function <code>entry</code>
can be invoked simultaneously from different threads, even in the presence
of concurrent accesses to <code>insert</code> and <code>erase</code> (as long
as the entry returned by <code>entry</code> is not the one which is being
erased).
</p>
<p>
A type <code>S</code> is said to be a <i>factory specifier</i> if:
<ol>
<li>One of the following conditions is satisfied:
<ol type="a">
<li><a href="#is_factory"><code>is_factory&lt;S&gt;::type</code></a> is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::true_</code></a>,</li>
<li><code>S</code> is of the form <a href="#factory_construct"><code>factory&lt;S'&gt;</code></a>.</li>
</ol>
</li>
<li><code>S</code>, or <code>S'</code> if (b) applies, is an
<a href="../../../mpl/doc/refmanual/lambda-expression.html"><code>MPL Lambda
Expression</code></a> such that invoking it with types (<code>Entry</code>,
<code>Key</code>) resolves to a factory type of <code>Entry</code> elements
(implicitly associated to <code>Key</code>).
</li>
</ol>
</p>
<h2><a name="factory_tag_synopsis">Header
<a href="../../../../boost/flyweight/factory_tag.hpp"><code>"boost/flyweight/factory_tag.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>struct</span> <span class=identifier>factory_marker</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>is_factory</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>factory</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<h3><a name="is_factory">Class template <code>is_factory</code></a></h3>
<p>
Unless specialized by the user, <code>is_factory&lt;T&gt;::type</code> is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::true_</code></a>
if <code>T</code> is derived from <code>factory_marker</code>, and it is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::false_</code></a>
otherwise.
</p>
<h3><a name="factory_construct">Class template <code>factory</code></a></h3>
<p>
<code>factory&lt;T&gt;</code> is a syntactic construct meant to indicate
that <code>T</code> is a factory specifier without resorting to the
mechanisms provided by the <code>is_factory</code> class template.
</p>
<h2><a name="hashed_factory_fwd_synopsis">Header
<a href="../../../../boost/flyweight/hashed_factory_fwd.hpp"><code>"boost/flyweight/hashed_factory_fwd.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Hash</span><span class=special>=</span><b>implementation defined</b><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Pred</span><span class=special>=</span><b>implementation defined</b><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>=</span><b>implementation defined</b>
<span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>hashed_factory_class</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Hash</span><span class=special>=</span><b>implementation defined</b><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Pred</span><span class=special>=</span><b>implementation defined</b><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>=</span><b>implementation defined</b>
<span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>hashed_factory</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
<code>hashed_factory_fwd.hpp</code> forward declares the class templates
<a href="#hashed_factory_class"><code>hashed_factory_class</code></a>
and <a href="#hashed_factory"><code>hashed_factory</code></a>.
</p>
<h2><a name="hashed_factory_synopsis">Header
<a href="../../../../boost/flyweight/hashed_factory.hpp"><code>"boost/flyweight/hashed_factory.hpp"</code></a> synopsis</a></h2>
<h3><a name="hashed_factory_class">Class template <code>hashed_factory_class</code></a></h3>
<p>
<code>hashed_factory_class</code> is a <a href="#factory"><code>Factory</code></a>
implemented with a hashed container.
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Hash</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Pred</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
<span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>hashed_factory_class</span>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=keyword>typedef</span> <b>implementation defined</b> <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>&amp;</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>&amp;</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span>
<span class=special>};</span>
</pre></blockquote>
<p>
<code>Hash</code> is a
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"><code>Default
Constructible</code></a>
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html"><code>Unary Function</code></a>
taking a single argument of type <code>Key</code> and returning a
value of type <code>std::size_t</code> in the range
<code>[0, std::numeric_limits&lt;std::size_t&gt;::max())</code>.
<code>Pred</code> is a
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"><code>Default
Constructible</code></a>
<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">
<code>Binary Predicate</code></a> inducing an equivalence relation
on elements of <code>Key</code>. It is required that
a <code>Hash</code> object return the same value for objects
equivalent under <code>Pred</code>.
The equivalence relation on <code>Key</code> associated to the factory is
that induced by <code>Pred</code>.
The default arguments for <code>Hash</code> and <code>Pred</code> are
<a href="../../../functional/hash/index.html"><code>boost::hash&lt;Key&gt;</code></a>
and <code>std::equal_to&lt;Key&gt;</code>, respectively.
<code>Allocator</code> must be an allocator of <code>Entry</code> objects
satisfying the associated C++ requirements at <b>[lib.allocator.requirements]</b>.
The default argument is <code>std::allocator&lt;Entry&gt;</code>. The internal
hashed container upon which <code>hashed_factory_class</code> is based is
constructed with default initialized objects of type <code>Hash</code>,
<code>Pred</code> and <code>Allocator</code>.
</p>
<h3><a name="hashed_factory">Class template <code>hashed_factory</code></a></h3>
<p>
<a href="#factory"><code>Factory Specifier</code></a> for <a href="#hashed_factory_class"><code>hashed_factory_class</code></a>.
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Hash</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Pred</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>hashed_factory</span><span class=special>;</span>
</pre></blockquote>
<p>
<code>hashed_factory&lt;Hash,Pred,Allocator&gt;</code> is an
<a href="../../../mpl/doc/refmanual/metafunction-class.html"><code>MPL Metafunction
Class</code></a> such that the type
</p>
<blockquote><pre>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>apply</span><span class=special>&lt;</span>
<span class=identifier>hashed_factory</span><span class=special>&lt;</span><span class=identifier>Hash</span><span class=special>,</span><span class=identifier>Pred</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span>
<span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
</pre></blockquote>
<p>
is the same as
</p>
<blockquote><pre>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>apply</span><span class=special>&lt;</span>
<span class=identifier>hashed_factory_class</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</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>Hash</span><span class=special>,</span><span class=identifier>Pred</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span>
<span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
</pre></blockquote>
<p>
This implies that <code>Hash</code>, <code>Pred</code> and <code>Allocator</code>
can be
<a href="../../../mpl/doc/refmanual/placeholder-expression.html"><code>MPL
Placeholder Expressions</code></a> resolving to the actual types used by
<code>hashed_factory_class</code>.
</p>
<h2><a name="set_factory_fwd_synopsis">Header
<a href="../../../../boost/flyweight/set_factory_fwd.hpp"><code>"boost/flyweight/set_factory_fwd.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>=</span><b>implementation defined</b><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>=</span><b>implementation defined</b>
<span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>set_factory_class</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>=</span><b>implementation defined</b><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>=</span><b>implementation defined</b>
<span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>set_factory</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
<code>set_factory_fwd.hpp</code> forward declares the class templates
<a href="#set_factory_class"><code>set_factory_class</code></a>
and <a href="#set_factory"><code>set_factory</code></a>.
</p>
<h2><a name="set_factory_synopsis">Header
<a href="../../../../boost/flyweight/set_factory.hpp"><code>"boost/flyweight/set_factory.hpp"</code></a> synopsis</a></h2>
<h3><a name="set_factory_class">Class template <code>set_factory_class</code></a></h3>
<p>
<code>set_factory_class</code> is a <a href="#factory"><code>Factory</code></a>
implemented on top of an orderded associative container.
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
<span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>set_factory_class</span>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=keyword>typedef</span> <b>implementation defined</b> <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>&amp;</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>&amp;</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span>
<span class=special>};</span>
</pre></blockquote>
<p>
<code>Compare</code> is a
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"><code>Default
Constructible</code></a>
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> on <code>Key</code>. Two <code>Key</code>s
<code>x</code> and <code>y</code> are considered equivalent if
<code>!c(x,y)&amp;&amp;!c(y,x)</code> for <code>c</code> of type <code>Compare</code>.
The default argument of <code>Compare</code> is <code>std::less&lt;Key&gt;</code>
<code>Allocator</code> must be an allocator of <code>Entry</code> objects
satisfying the associated C++ requirements at <b>[lib.allocator.requirements]</b>.
The default argument is <code>std::allocator&lt;Entry&gt;</code>. The internal
container upon which <code>set_factory_class</code> is based is
constructed with default initialized objects of type <code>Compare</code>
and <code>Allocator</code>.
</p>
<h3><a name="set_factory">Class template <code>set_factory</code></a></h3>
<p>
<a href="#factory"><code>Factory Specifier</code></a> for <a href="#set_factory_class"><code>set_factory_class</code></a>.
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>set_factory</span><span class=special>;</span>
</pre></blockquote>
<p>
<code>set_factory&lt;Compare,Allocator&gt;</code> is an
<a href="../../../mpl/doc/refmanual/metafunction-class.html"><code>MPL Metafunction
Class</code></a> such that the type
</p>
<blockquote><pre>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>apply</span><span class=special>&lt;</span>
<span class=identifier>set_factory</span><span class=special>&lt;</span><span class=identifier>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span>
<span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
</pre></blockquote>
<p>
is the same as
</p>
<blockquote><pre>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>apply</span><span class=special>&lt;</span>
<span class=identifier>set_factory_class</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</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>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span>
<span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
</pre></blockquote>
<p>
This implies that <code>Compare</code> and <code>Allocator</code>
can be
<a href="../../../mpl/doc/refmanual/placeholder-expression.html"><code>MPL
Placeholder Expressions</code></a> resolving to the actual types used by
<code>set_factory_class</code>.
</p>
<h2><a name="assoc_container_factory_fwd_synopsis">Header
<a href="../../../../boost/flyweight/assoc_container_factory_fwd.hpp"><code>"boost/flyweight/assoc_container_factory_fwd.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>&lt;</span><span class=keyword>typename</span> <span class=identifier>Container</span><span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>assoc_container_factory_class</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>ContainerSpecifier</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>assoc_container_factory</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
<code>assoc_container_factory_fwd.hpp</code> forward declares the class templates
<a href="#assoc_container_factory_class"><code>assoc_container_factory_class</code></a>
and <a href="#assoc_container_factory"><code>assoc_container_factory</code></a>.
</p>
<h2><a name="assoc_container_factory_synopsis">Header
<a href="../../../../boost/flyweight/assoc_container_factory.hpp"><code>"boost/flyweight/assoc_container_factory.hpp"</code></a> synopsis</a></h2>
<h3><a name="assoc_container_factory_class">Class template <code>assoc_container_factory_class</code></a></h3>
<p>
<code>assoc_container_factory_class</code> wraps a suitable associative container
to provide a <a href="#factory"><code>Factory</code></a> interface.
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Container</span><span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>assoc_container_factory_class</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>Container</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=keyword>typename</span> <span class=identifier>Container</span><span class=special>::</span><span class=identifier>value_type</span><span class=special>&amp;</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=keyword>typename</span> <span class=identifier>Container</span><span class=special>::</span><span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span>
<span class=special>};</span>
</pre></blockquote>
<p>
<code>Container</code> must be an (ordered or unordered) associative container
such that
<ol>
<li><code>Container::key_type</code> is the same as
<code>Container::value_type</code> (which is the entry type associated to
the factory).
</li>
<li>Unique keys (rather than equivalent keys) are supported.</li>
<li><code>Container</code> is <i>stable</i>, i.e. its iterators are not
invalidated upon insert or erase operations.</li>
</ol>
The equivalence relation associated to <code>assoc_container_factory_class</code>
is the one induced by <code>Container</code>. If equivalence of elements
of <code>Container::value_type</code> is determined solely on the basis of a
type <code>value_type'</code> to which <code>value_type</code> is
implicitly convertible, then <code>assoc_container_factory_class</code> is
a factory of entries of type <code>value_type</code> implicitly associated to
<code>value_type'</code>. For example, the instantiation
</p>
<blockquote><pre>
<span class=identifier>assoc_container_factory_class</span><span class=special>&lt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special>&lt;</span><span class=identifier>derived</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>base</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=comment>// derived inherits from base</span>
<span class=special>&gt;</span>
</pre></blockquote>
<p>
is a factory of <code>derived</code> elements implicitly associated to
<code>base</code>.
</p>
<h3><a name="assoc_container_factory">Class template <code>assoc_container_factory</code></a></h3>
<p>
<a href="#factory"><code>Factory Specifier</code></a> for <a href="#assoc_container_factory_class"><code>assoc_container_factory_class</code></a>.
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>ContainerSpecifier</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>assoc_container_factory</span><span class=special>;</span>
</pre></blockquote>
<p>
<code>ContainerSpecifier</code> must be an
<a href="../../../mpl/doc/refmanual/lambda-expression.html"><code>MPL Lambda
Expression</code></a> resolving, when invoked with (<code>Entry</code>,
<code>Key</code>), to a type <code>Container</code> such that
<code>assoc_container_factory_class&lt;Container&gt;</code> is a factory
of <code>Entry</code> elements implicitly associated to <code>Key</code>.
</p>
<hr>
<div class="prev_link"><a href="tags.html"><img src="../prev.gif" alt="tags" border="0"><br>
Tags
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="holders.html"><img src="../next.gif" alt="holders" border="0"><br>
Holders
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised August 13th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

View File

@@ -0,0 +1,630 @@
<!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 - flyweight reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="index.html">
<link rel="up" href="index.html">
<link rel="next" href="key_value.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight
<code>flyweight</code> reference</h1>
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="key_value.html"><img src="../next.gif" alt="key-value flyweights" border="0"><br>
Key-value flyweights
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#flyweight_fwd_synopsis">Header
<code>"boost/flyweight/flyweight_fwd.hpp"</code> synopsis</a></li>
<li><a href="#synopsis">Header
<code>"boost/flyweight/flyweight.hpp"</code> synopsis</a>
<ul>
<li><a href="#flyweight">Class template <code>flyweight</code></a>
<ul>
<li><a href="#instantiation_types">Instantiation types</a></li>
<li><a href="#static_init">Static data initialization</a></li>
<li><a href="#constructors">Constructors, copy and assignment</a></li>
<li><a href="#convertibility">Convertibility to the underlying types</a></li>
<li><a href="#modifiers">Modifiers</a></li>
<li><a href="#comparison">Comparison operators</a></li>
<li><a href="#specialized">Specialized algorithms</a></li>
<li><a href="#config_macros">Configuration macros</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>
<a name="flyweight_fwd_synopsis">Header
<a href="../../../../boost/flyweight/flyweight_fwd.hpp"><code>"boost/flyweight/flyweight_fwd.hpp"</code></a>
synopsis</a>
</h2>
<blockquote><pre>
<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>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>T</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Arg1</span><span class=special>=</span><b>implementation defined</b><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Arg2</span><span class=special>=</span><b>implementation defined</b><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Arg3</span><span class=special>=</span><b>implementation defined</b><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Arg4</span><span class=special>=</span><b>implementation defined</b><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Arg5</span><span class=special>=</span><b>implementation defined</b>
<span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>flyweight</span><span class=special>;</span>
<span class=comment>// comparison:
// <b>OP</b> is any of ==,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>T1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg11</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Arg15</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>T2</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg21</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Arg25</span>
<span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <span class=identifier><b><i>OP</i></b></span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T1</span><span class=special>,</span><span class=identifier>Arg11</span><span class=special>,...,</span><span class=identifier>Arg15</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T2</span><span class=special>,</span><span class=identifier>Arg21</span><span class=special>,...,</span><span class=identifier>Arg25</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>T1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg11</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Arg15</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>T2</span>
<span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <span class=identifier><b><i>OP</i></b></span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T1</span><span class=special>,</span><span class=identifier>Arg11</span><span class=special>,...,</span><span class=identifier>Arg15</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>T2</span><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>T1</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>T2</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg21</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Arg25</span>
<span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <span class=identifier><b><i>OP</i></b></span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>T1</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T2</span><span class=special>,</span><span class=identifier>Arg21</span><span class=special>,...,</span><span class=identifier>Arg25</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=comment>// specialized algorithms:</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg1</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Arg5</span><span class=special>&gt;</span>
<span class=keyword>inline</span> <span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Arg1</span><span class=special>,...,</span><span class=identifier>Arg5</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Arg1</span><span class=special>,...,</span><span class=identifier>Arg5</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>ElemType</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Traits</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>T</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg1</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Arg5</span>
<span class=special>&gt;</span>
<span class=keyword>inline</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>basic_ostream</span><span class=special>&lt;</span><span class=identifier>ElemType</span><span class=special>,</span><span class=identifier>Traits</span><span class=special>&gt;&amp;</span> <span class=keyword>operator</span><span class=special>&lt;&lt;(</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>basic_ostream</span><span class=special>&lt;</span><span class=identifier>ElemType</span><span class=special>,</span><span class=identifier>Traits</span><span class=special>&gt;&amp;</span> <span class=identifier>out</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Arg1</span><span class=special>,...,</span><span class=identifier>Arg5</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>ElemType</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Traits</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>T</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg1</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Arg5</span>
<span class=special>&gt;</span>
<span class=keyword>inline</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>basic_ostream</span><span class=special>&lt;</span><span class=identifier>ElemType</span><span class=special>,</span><span class=identifier>Traits</span><span class=special>&gt;&amp;</span> <span class=keyword>operator</span><span class=special>&gt;&gt;(</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>basic_istream</span><span class=special>&lt;</span><span class=identifier>ElemType</span><span class=special>,</span><span class=identifier>Traits</span><span class=special>&gt;&amp;</span> <span class=identifier>in</span><span class=special>,</span>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Arg1</span><span class=special>,...,</span><span class=identifier>Arg5</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=keyword>using</span> <span class=identifier>flyweights</span><span class=special>::</span><span class=identifier>flyweight</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
<code>flyweight_fwd.hpp</code> forward declares the class template
<a href="#flyweight"><code>flyweight</code></a> and its associated global functions.
</p>
<h2>
<a name="synopsis">Header
<a href="../../../../boost/flyweight/flyweight.hpp"><code>"boost/flyweight/flyweight.hpp"</code></a>
synopsis</a>
</h2>
<h3><a name="flyweight">
Class template <code>flyweight</code>
</a></h3>
<p>
Objects of type <code>flyweight&lt;...&gt;</code> provide access to immutable
values of type <code>flyweight&lt;...&gt;::value_type</code>, with the following advantages over using
plain <code>value_type</code> objects:
<ul>
<li>Flyweight objects with equivalent value share the same representation
(the associated <code>value_type</code> object).
</li>
<li>The size of flyweights is typically that of a pointer, which is in general
smaller than <code>sizeof(value_type)</code>.
</li>
</ul>
So, if the level of redundancy (ratio of total objects to different values)
is high enough, substituting a suitable instantiation of <code>flyweight</code>
for <code>value_type</code> results in a reduction in memory usage.
</p>
<p>
<code>flyweight</code> is parameterized according to some aspects:
<ul>
<li>Types <code>key_value</code> and <code>value_type</code>
(possibly equal), where <code>key_type</code> serves as a
key type to lookup and construct internal shared instances of
objects of <code>value_type</code>.
</li>
<li>An optional <a href="tags.html#tag">tag</a> type meant to syntactically
differentiate between otherwise identical instantiations.
</li>
<li>The <a href="factories.html#factory">factory class</a> used to store
and retrieve the shared value objects.
</li>
<li>The type of <a href="holders.html#holder">holder</a> used to
instantiate the flyweight factory and a mutex object, both of
which are unique to each specialization of the <code>flyweight</code>
class template.
</li>
<li>A <a href="locking.html#locking">locking policy</a> determining
the synchronization mechanisms for internal access to shared resources.
</li>
<li>A <a href="tracking.html#tracking">tracking policy</a> which controls
how values are treated when all their associated flyweight objects are
destroyed.
</li>
</ul>
These aspects impact the internal structure and behavior
of the <code>flyweight</code> instantiation in the following manner:
<ul>
<li>Each instantation of <code>flyweight</code> internally owns
a unique factory object and a unique synchronization
<a href="locking.html#preliminary">mutex</a> object, both of which
are created through the use of an associated holder type.
</li>
<li>The flyweight factory stores elements of an undisclosed type
<code>Entry</code> that is implicitly convertible to
<code>const key_type&amp;</code> and also stores a subobject of
<code>value_type</code>. Every flyweight object is associated
to a <code>value_type</code> subobject of some <code>Entry</code>
stored in the factory.
</li>
<li>The associated mutex object is used to protect all invocations
to the insertion and deletion functions of the internal flyweight
factory.
</li>
<li>Each flyweight object internally stores a value of some
undisclosed type <code>Handle</code>. <code>Handle</code> and
the <code>Entry</code> type referred to above are obtained
from invocations to the associated tracking policy, in the
manner described for this concept.
</li>
</ul>
In what follows, we implicitly assume that <code>key_type</code> equivalence
refers to the equivalence relationship induced by the factory class used.
Also, two values of <code>value_type</code> are considered equivalent
if they are constructed from equivalent keys, or are copies of
objects constructed from equivalent keys.
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>T</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Arg1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg2</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg3</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg4</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg5</span>
<span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>flyweight</span>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=keyword>typedef</span> <span class=identifier><b>dependent on T</b></span> <span class=identifier>key_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier><b>dependent on T</b></span> <span class=identifier>value_type</span><span class=special>;</span>
<span class=comment>// static data initialization:</span>
<span class=keyword>static</span> <span class=keyword>bool</span> <span class=identifier>init</span><span class=special>();</span>
<span class=keyword>class</span> <span class=identifier>initializer</span><span class=special>{</span><span class=keyword>public</span><span class=special>:</span><span class=identifier>initializer</span><span class=special>();</span><span class=special>};</span>
<span class=comment>// construct/copy/destroy:</span>
<span class=identifier>flyweight</span><span class=special>();</span>
<span class=identifier>flyweight</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>flyweight</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>flyweight</span><span class=special>(</span><span class=identifier>flyweight</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=comment>// forwarding constructors:
// n is implementation defined. All combinations of constant
// and non constant reference arguments are provided.</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T0</span><span class=special>&gt;</span>
<span class=keyword>explicit</span> <span class=identifier>flyweight</span><span class=special>([</span><span class=keyword>const</span><span class=special>]</span> <span class=identifier>T0</span><span class=special>&amp;</span> <span class=identifier>t0</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T0</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>T1</span><span class=special>&gt;</span>
<span class=identifier>flyweight</span><span class=special>([</span><span class=keyword>const</span><span class=special>]</span> <span class=identifier>T0</span><span class=special>&amp;</span> <span class=identifier>t0</span><span class=special>,[</span><span class=keyword>const</span><span class=special>]</span> <span class=identifier>T1</span><span class=special>&amp;</span> <span class=identifier>t1</span><span class=special>);</span>
<span class=special>...</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T0</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Tn</span><span class=special>-</span><span class=number>1</span><span class=special>&gt;</span>
<span class=identifier>flyweight</span><span class=special>([</span><span class=keyword>const</span><span class=special>]</span> <span class=identifier>T0</span><span class=special>&amp;</span> <span class=identifier>t0</span><span class=special>,...,[</span><span class=keyword>const</span><span class=special>]</span> <span class=identifier>Tn</span><span class=special>-</span><span class=number>1</span><span class=special>&amp;</span> <span class=identifier>tn</span><span class=special>-</span><span class=number>1</span><span class=special>);</span>
<span class=identifier>flyweight</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <span class=identifier>flyweight</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>flyweight</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=comment>// convertibility to underlying type:</span>
<span class=keyword>const</span> <span class=identifier>key_type</span><span class=special>&amp;</span> <span class=identifier>get_key</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>get</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>operator</span> <span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;()</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// modifiers:</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><span class=identifier>flyweight</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=special>};</span>
</pre></blockquote>
<h4><a name="instantiation_types">Instantiation types</a></h4>
<p>
<code>T</code> can be either:
<ul>
<li>An arbitrary type,</li>
<li>a type of the form
<a href="key_value.html#key_value_construct"><code>key_value&lt;Key,Value[,KeyFromValue]&gt;</code></a>.</li>
</ul>
In the first case, the nested types <code>key_type</code> and <code>value_type</code>
are both equal to <code>T</code>. In the second case, <code>key_type</code>=<code>Key</code>,
<code>value_type</code>=<code>Value</code>; we say then that the instantiation
of <code>flyweight</code> is a <i>key-value</i> flyweight.
<code>value_type</code> is the type of the values flyweight objects give access to,
while value lookup is based on associated <code>key_type</code> values.
<code>key_value</code> must be
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
and <code>value_type</code> must be constructible from <code>key_type</code>;
additionally, <code>key_value</code> must
conform to any extra requirements imposed by the type of factory used.
For key-value flyweights, it is guaranteed that the creation or assignment of a flyweight
object results in at most one construction (or copy construction in some
particular cases) of an object
of <code>value_type</code>, and this construction only occurs in the case that no
equivalent value existed previously in the flyweight factory.
</p>
<p>
The types <code>Arg1</code>, ... , <code>Arg5</code>, if provided, must be any
of the following, in no particular order:
<ul>
<li>A <a href="tags.html#tag">tag</a>,</li>
<li>a <a href="factories.html#factory">factory specifier</a>,</li>
<li>a <a href="holders.html#holder">holder specifier</a>,</li>
<li>a <a href="locking.html#locking">locking policy</a>,</li>
<li>a <a href="tracking.html#tracking">tracking policy</a>.</li>
</ul>
No aspect can be specified twice. Each internal component of the
<code>flyweight</code> instantiation is obtained through use of the
corresponding specifier; for instance, the factory results from a
certain (MPL) invocation of the given factory specifier, the internal
mutex from the given locking policy, etc.
The default configuration arguments are:
<ul>
<li>No tagging,</li>
<li><a href="factories.html#hashed_factory"><code>hashed_factory&lt;&gt;</code></a>,</li>
<li><a href="holders.html#static_holder"><code>static_holder</code></a>,</li>
<li><a href="locking.html#simple_locking"><code>simple_locking</code></a>,</li>
<li><a href="tracking.html#refcounted"><code>refcounted</code></a> tracking policy.</li>
</ul>
</p>
<h4><a name="static_init">Static data initialization</a></h4>
<p>
The static data internal to a given <code>flyweight</code> instantiation
(factory instance, etc.) is constructed during the dynamic initialization
phase of the program and always before the first program-wide use of the
instantiated class. The following utilities can be
used when more control about the moment of construction is required.
</p>
<code>static bool init();</code>
<blockquote>
<b>Effects:</b> After execution of this function the static data associated
to the instantiation of <code>flyweight</code> is guaranteed to be
constructed.<br>
<b>Note:</b> Concurrent execution of this function is not thread safe.
</blockquote>
<code>initializer::initializer();</code>
<blockquote>
<b>Effects:</b> Executes <code>init()</code>.
</blockquote>
<h4><a name="constructors">Constructors, copy and assignment</a></h4>
<code>flyweight();</code>
<blockquote>
<b>Requires:</b> <code>key_type</code> is
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"><code>Default
Constructible</code></a>.<br>
<b>Effects:</b> Constructs a <code>flyweight</code> object associated
with value <code>value_type(key_type())</code>.
</blockquote>
<code>flyweight(const flyweight&amp; x);<br>
flyweight(flyweight&amp; x);</code>
<blockquote>
<b>Effects:</b> Constructs a <code>flyweight</code> object with value
<code>x.get()</code>.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<a name="fwd_ctors">
<code>template&lt;typename T0&gt;<br>
explicit flyweight([const] T0&amp; t0);<br>
template&lt;typename T0,typename T1&gt;<br>
flyweight([const] T0&amp; t0,[const] T1&amp; t1);<br>
...<br>
template&lt;typename T0,...,typename Tn-1&gt;<br>
flyweight([const] T0&amp; t0,...,[const] Tn-1&amp; tn-1);</code></a>
<blockquote>
<b>Effects:</b> Constructs a <code>flyweight</code> object with value
<code>value_type(key_type(t0,...,ti))</code>, up to an implementation defined number
of arguments.<br>
<b>Note:</b> In this implementation, the maximum number of arguments
can be globally <a href="#limit_num_ctor_args">configured</a> by the user.
</blockquote>
<code>flyweight&amp; operator=(const flyweight&amp; x);</code>
<blockquote>
<b>Effects:</b> Associates the <code>flyweight</code> object with the same value
as <code>x</code>.<br>
<b>Returns:</b> <code>*this</code>.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<code>flyweight&amp; operator=(const value_type&amp; x);</code>
<blockquote>
<b>Requires:</b> If <code>flyweight</code> is key-value,
<code>value_type</code> is
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
and the
<a href="key_value.html#key_extractor"><code>Key Extractor</code></a>
<code>KeyFromValue</code> must have been supplied as part of the
<code>key_value&lt;&gt;</code> construct.<br>
<b>Effects:</b> Associates the <code>flyweight</code> object with a
copy of <code>x</code> or with a <code>value_type</code> constructed
from a key equivalent to that associated to <code>x</code>. For non-key-value
flyweights, <code>x</code> is its own key; for key-value flyweights,
the key is extracted through use of an object of type <code>KeyFromValue</code>.<br>
<b>Returns:</b> <code>*this</code>.<br>
</blockquote>
<h4><a name="convertibility">Convertibility to the underlying types</a></h4>
<code>const key_type&amp; get_key()const;</code>
<blockquote>
<b>Return:</b> A copy of the key used to construct the
<code>value_type</code> associated to the <code>flyweight</code>
object.<br>
<b>Exception safety:</b> If <code>flyweight</code> is not key-value or
if <code>KeyFromValue</code> was not provided, <code>nothrow</code>.
</blockquote>
<code>const value_type&amp; get()const;<br>
operator const value_type&amp;()const;</code>
<blockquote>
<b>Return:</b> The value associated to the <code>flyweight</code>
object.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<h4><a name="modifiers">Modifiers</a></h4>
<code>void swap(flyweight&amp; x);</code>
<blockquote>
<b>Effects:</b> Swaps the associations to <code>value_type</code>s each
flyweight object has. No swapping of <code>key_type</code> or
<code>value_type</code> objects is done.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<h4><a name="comparison">Comparison operators</a></h4>
<code>template&lt;<br>
&nbsp;&nbsp;typename T1,typename Arg11,...,typename Arg15,<br>
&nbsp;&nbsp;typename T2,typename Arg21,...,typename Arg25<br>
&gt;<br>
bool operator ==(<br>
&nbsp;&nbsp;const flyweight&lt;T1,Arg11,...,Arg15&gt;&amp; x,<br>
&nbsp;&nbsp;const flyweight&lt;T2,Arg21,...,Arg25&gt;&amp; y);</code>
<blockquote>
<b>Returns:</b> If <code>x</code> and <code>y</code> are of the same type, returns
<code>true</code> if and only if they are associated to the same value; if
<code>x</code> and <code>y</code> have different types, returns
<code>x.get()==y.get()</code>.<br>
<b>Exception safety:</b> If <code>x</code> and <code>y</code> are of the same type,
<code>nothrow</code>.
</blockquote>
<code>template&lt;<br>
&nbsp;&nbsp;typename T1,typename Arg11,...,typename Arg15,<br>
&nbsp;&nbsp;typename T2<br>
&gt;<br>
bool operator ==(const flyweight&lt;T1,Arg11,...,Arg15&gt;&amp; x,const T2&amp; y);</code>
<blockquote>
<b>Returns:</b> <code>x.get()==y</code>.
</blockquote>
<code>template&lt;<br>
&nbsp;&nbsp;typename T1,<br>
&nbsp;&nbsp;typename T2,typename Arg21,...,typename Arg25<br>
&gt;<br>
bool operator ==(const T1&amp; x,const flyweight&lt;T2,Arg21,...,Arg25&gt;&amp; y);</code>
<blockquote>
<b>Returns:</b> <code>x()==y.get()</code>.
</blockquote>
<code>template&lt;<br>
&nbsp;&nbsp;typename T1,typename Arg11,...,typename Arg15,<br>
&nbsp;&nbsp;typename T2,typename Arg21,...,typename Arg25<br>
&gt;<br>
bool operator &lt;(<br>
&nbsp;&nbsp;const flyweight&lt;T1,Arg11,...,Arg15&gt;&amp; x,<br>
&nbsp;&nbsp;const flyweight&lt;T2,Arg21,...,Arg25&gt;&amp; y);</code>
<blockquote>
<b>Returns:</b> <code>x.get()&lt;y.get()</code>.
</blockquote>
<code>template&lt;<br>
&nbsp;&nbsp;typename T1,typename Arg11,...,typename Arg15,<br>
&nbsp;&nbsp;typename T2<br>
&gt;<br>
bool operator &lt;(const flyweight&lt;T1,Arg11,...,Arg15&gt;&amp; x,const T2&amp; y);</code>
<blockquote>
<b>Returns:</b> <code>x.get()&lt;y</code>.
</blockquote>
<code>template&lt;<br>
&nbsp;&nbsp;typename T1,<br>
&nbsp;&nbsp;typename T2,typename Arg21,...,typename Arg25<br>
&gt;<br>
bool operator &lt;(const T1&amp; x,const flyweight&lt;T2,Arg21,...,Arg25&gt;&amp; y);</code>
<blockquote>
<b>Returns:</b> <code>x()&lt;y.get()</code>.
</blockquote>
<code>template&lt;<br>
&nbsp;&nbsp;typename T1,typename Arg11,...,typename Arg15,<br>
&nbsp;&nbsp;typename T2,typename Arg21,...,typename Arg25<br>
&gt;<br>
bool operator <b><i>OP</i></b>(<br>
&nbsp;&nbsp;const flyweight&lt;T1,Arg11,...,Arg15&gt;&amp; x,<br>
&nbsp;&nbsp;const flyweight&lt;T2,Arg21,...,Arg25&gt;&amp; y);<br>
template&lt;<br>
&nbsp;&nbsp;typename T1,typename Arg11,...,typename Arg15,<br>
&nbsp;&nbsp;typename T2<br>
&gt;<br>
bool operator <b><i>OP</i></b>(const flyweight&lt;T1,Arg11,...,Arg15&gt;&amp; x,const T2&amp; y);</br>
template&lt;<br>
&nbsp;&nbsp;typename T1,<br>
&nbsp;&nbsp;typename T2,typename Arg21,...,typename Arg25<br>
&gt;<br>
bool operator <b><i>OP</i></b>(const T1&amp; x,const flyweight&lt;T2,Arg21,...,Arg25&gt;&amp; y);</code>
<p>
(<code><b><i>OP</i></b></code> is any of <code>!=</code>, <code>></code>,
<code>>=</code>, <code>&lt;=</code>.)
</p>
<blockquote>
<b>Returns:</b> <code>true</code> if and only if
<blockquote>
<code>!(x==y)</code> (<code><b><i>OP</i></b></code> is <code>!=</code>),<br>
<code>&nbsp;&nbsp;y&lt;&nbsp;x&nbsp;</code> (<code><b><i>OP</i></b></code> is <code>>&nbsp;</code>),<br>
<code>!(x&lt;&nbsp;y)</code> (<code><b><i>OP</i></b></code> is <code>>=</code>),<br>
<code>!(y&lt;&nbsp;x)</code> (<code><b><i>OP</i></b></code> is <code>&lt;=</code>).
</blockquote>
</blockquote>
<h4><a name="specialized">Specialized algorithms</a></h4>
<code>template&lt;typename T,typename Arg1,...,typename Arg5&gt;<br>
inline void swap(<br>
&nbsp;&nbsp;flyweight&lt;T,Arg1,...,Arg5&gt;&amp; x,flyweight&lt;T,Arg1,...,Arg5&gt;&amp; y);</code>
<blockquote>
<b>Effects:</b> <code>x.swap(y)</code>.
</blockquote>
<code>template&lt;<br>
&nbsp;&nbsp;typename ElemType,typename Traits, <br>
&nbsp;&nbsp;typename T,typename Arg1,...,typename Arg5<br>
&gt;<br>
inline std::basic_ostream&lt;ElemType,Traits&gt;&amp; operator&lt;&lt;(<br>
&nbsp;&nbsp;std::basic_ostream&lt;ElemType,Traits&gt;&amp; out,<br>
&nbsp;&nbsp;const flyweight&lt;T,Arg1,...,Arg5&gt;&amp; x);</code>
<blockquote>
<b>Effects:</b> <code>out&lt;&lt;x.get()</code>.<br>
<b>Returns:</b> <code>out</code>.
</blockquote>
<code>template&lt;<br>
&nbsp;&nbsp;typename ElemType,typename Traits, <br>
&nbsp;&nbsp;typename T,typename Arg1,...,typename Arg5<br>
&gt;<br>
inline std::basic_ostream&lt;ElemType,Traits&gt;&amp; operator&gt;&gt;(<br>
&nbsp;&nbsp;std::basic_istream&lt;ElemType,Traits&gt;&amp; in,<br>
&nbsp;&nbsp;flyweight&lt;T,Arg1,...,Arg5&gt;&amp; x);</code>
<blockquote>
<b>Requires:</b> If <code>flyweight</code> is key-value,
<code>value_type</code> is
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
and the
<a href="key_value.html#key_extractor"><code>Key Extractor</code></a>
<code>KeyFromValue</code> must have been supplied as part of the
<code>key_value&lt;&gt;</code> construct.<br>
<b>Effects:</b> Reads an object of type <code>value_type</code> from <code>in</code>
and assigns it to <code>x</code>.<br>
<b>Returns:</b> <code>in</code>.
</blockquote>
<h4><a name="config_macros">Configuration macros</a></h4>
<a name="limit_num_ctor_args">
<code>BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS</code></a>
<blockquote>
<b>Effects:</b> Globally define this macro to set the maximum number of
arguments accepted by <code>flyweight</code>
<a href="#fwd_ctors">forwarding constructors</a>, which by default
is 5.
</blockquote>
<hr>
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="key_value.html"><img src="../next.gif" alt="key-value flyweights" border="0"><br>
Key-value flyweights
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised December 2nd 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

243
doc/reference/holders.html Normal file
View File

@@ -0,0 +1,243 @@
<!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 - Holders reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="factories.html">
<link rel="up" href="index.html">
<link rel="next" href="locking.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight
Holders reference</h1>
<div class="prev_link"><a href="factories.html"><img src="../prev.gif" alt="factories" border="0"><br>
Factories
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="locking.html"><img src="../next.gif" alt="locking policies" border="0"><br>
Locking policies
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#holder">Holders and holder specifiers</a></li>
<li><a href="#holder_tag_synopsis">Header
<code>"boost/flyweight/holder_tag.hpp"</code> synopsis</a>
<ul>
<li><a href="#is_holder">Class template <code>is_holder</code></a></li>
<li><a href="#holder_construct">Class template <code>holder</code></a></li>
</ul>
</li>
<li><a href="#static_holder_fwd_synopsis">Header
<code>"boost/flyweight/static_holder_fwd.hpp"</code> synopsis</a>
</li>
<li><a href="#static_holder_synopsis">Header
<code>"boost/flyweight/static_holder.hpp"</code> synopsis</a>
<ul>
<li><a href="#static_holder_class">Class template <code>static_holder_class</code></a></li>
<li><a href="#static_holder">Class <code>static_holder</code></a></li>
</ul>
</li>
<li><a href="#intermodule_holder_fwd_synopsis">Header
<code>"boost/flyweight/intermodule_holder_fwd.hpp"</code> synopsis</a>
</li>
<li><a href="#intermodule_holder_synopsis">Header
<code>"boost/flyweight/intermodule_holder.hpp"</code> synopsis</a>
<ul>
<li><a href="#intermodule_holder_class">Class template <code>intermodule_holder_class</code></a></li>
<li><a href="#intermodule_holder">Class <code>intermodule_holder</code></a></li>
</ul>
</li>
</ul>
<h2><a name="holder">Holders and holder specifiers</a></h2>
<p>
Given a type <code>C</code>, a type <code>Holder</code> is said to be a <i>holder
of <code>C</code></i> if the expression <code>Holder::get()</code> returns
a reference to a default initialized <code>C</code> object unique to
<code>Holder</code>. No invocation of <code>Holder::get()</code>, except possibly
the first one in the program, does throw.
<a href="flyweight.html#flyweight"><code>flyweight</code></a>
privately uses a holder to instantiate a <a href="factories.html#factory">factory</a>
and some additional data (like a <a href="locking.html#preliminary">mutex</a> for
internal synchronization) unique to each instantiation type of the class template.
</p>
<p>
A type <code>S</code> is a <i>holder specifier</i> if:
<ol>
<li>One of the following conditions is satisfied:
<ol type="a">
<li><a href="#is_holder"><code>is_holder&lt;S&gt;::type</code></a> is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::true_</code></a>,</li>
<li><code>S</code> is of the form <a href="#holder_construct"><code>holder&lt;S'&gt;</code></a>.</li>
</ol>
</li>
<li><code>S</code>, or <code>S'</code> if (b) applies, is an
<a href="../../../mpl/doc/refmanual/lambda-expression.html"><code>MPL Lambda
Expression</code></a> such that invoking it with type <code>C</code> resolves to
a holder of <code>C</code>.
</li>
</ol>
</p>
<h2><a name="holder_tag_synopsis">Header
<a href="../../../../boost/flyweight/holder_tag.hpp"><code>"boost/flyweight/holder_tag.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>struct</span> <span class=identifier>holder_marker</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>is_holder</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>holder</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<h3><a name="is_holder">Class template <code>is_holder</code></a></h3>
<p>
Unless specialized by the user, <code>is_holder&lt;T&gt;::type</code> is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::true_</code></a>
if <code>T</code> is derived from <code>holder_marker</code>, and it is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::false_</code></a>
otherwise.
</p>
<h3><a name="holder_construct">Class template <code>holder</code></a></h3>
<p>
<code>holder&lt;T&gt;</code> is a syntactic construct meant to indicate
that <code>T</code> is a holder specifier without resorting to the
mechanisms provided by the <code>is_holder</code> class template.
</p>
<h2><a name="static_holder_fwd_synopsis">Header
<a href="../../../../boost/flyweight/static_holder_fwd.hpp"><code>"boost/flyweight/static_holder_fwd.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>&lt;</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>static_holder_class</span><span class=special>;</span>
<span class=keyword>struct</span> <span class=identifier>static_holder</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
<code>static_holder_fwd.hpp</code> forward declares
<a href="#static_holder_class"><code>static_holder_class</code></a>
and <a href="#static_holder"><code>static_holder</code></a>.
</p>
<h2><a name="static_holder_synopsis">Header
<a href="../../../../boost/flyweight/static_holder.hpp"><code>"boost/flyweight/static_holder.hpp"</code></a> synopsis</a></h2>
<h3><a name="static_holder_class">Class template <code>static_holder_class</code></a></h3>
<p>
<code>static_holder_class&lt;C&gt;</code> keeps its unique instance of <code>C</code> as a
local static object.
</p>
<h3><a name="static_holder">Class <code>static_holder</code></a></h3>
<p>
<a href="#holder"><code>Holder Specifier</code></a> for <a href="#static_holder_class"><code>static_holder_class</code></a>.
</p>
<h2><a name="intermodule_holder_fwd_synopsis">Header
<a href="../../../../boost/flyweight/intermodule_holder_fwd.hpp"><code>"boost/flyweight/intermodule_holder_fwd.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>&lt;</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>intermodule_holder_class</span><span class=special>;</span>
<span class=keyword>struct</span> <span class=identifier>intermodule_holder</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
<code>intermodule_holder_fwd.hpp</code> forward declares
<a href="#intermodule_holder_class"><code>intermodule_holder_class</code></a>
and <a href="#intermodule_holder"><code>intermodule_holder</code></a>.
</p>
<h2><a name="intermodule_holder_synopsis">Header
<a href="../../../../boost/flyweight/intermodule_holder.hpp"><code>"boost/flyweight/intermodule_holder.hpp"</code></a> synopsis</a></h2>
<h3><a name="intermodule_holder_class">Class template <code>intermodule_holder_class</code></a></h3>
<p>
<code>intermodule_holder_class&lt;C&gt;</code> maintains a <code>C</code>
instance which is unique even across different dynamically linked modules of
the program using this same type. In general, this guarantee is not provided by
<a href="#static_holder_class"><code>static_holder_class</code></a>, as most
C++ implementations are not able to merge duplicates of static variables stored
in different dynamic modules of a program.
</p>
<h3><a name="intermodule_holder">Class <code>intermodule_holder</code></a></h3>
<p>
<a href="#holder"><code>Holder Specifier</code></a> for <a href="#intermodule_holder_class"><code>intermodule_holder_class</code></a>.
</p>
<hr>
<div class="prev_link"><a href="factories.html"><img src="../prev.gif" alt="factories" border="0"><br>
Factories
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="locking.html"><img src="../next.gif" alt="locking policies" border="0"><br>
Locking policies
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised August 11th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

158
doc/reference/index.html Normal file
View File

@@ -0,0 +1,158 @@
<!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 - Reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="lambda_expressions.html">
<link rel="up" href="../index.html">
<link rel="next" href="../tutorial/lambda_expressions.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Reference</h1>
<div class="prev_link"><a href="../tutorial/lambda_expressions.html"><img src="../prev.gif" alt="annex: MPL lambda expressions" border="0"><br>
Annex: MPL lambda expressions
</a></div>
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="flyweight.html"><img src="../next.gif" alt="flyweight reference" border="0"><br>
<code>flyweight</code> reference
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#headers">Header summary</a></li>
<li><a href="#flyweight_synopsis">Header
<code>"boost/flyweight.hpp"</code> synopsis</a></li>
<li><a href="flyweight.html">Class template <code>flyweight</code></a></li>
<li><a href="key_value.html">Key-value flyweights</a></li>
<li><a href="tags.html">Tags</a></li>
<li><a href="factories.html">Factories</a></li>
<li><a href="holders.html">Holders</a></li>
<li><a href="locking.html">Locking policies</a></li>
<li><a href="tracking.html">Tracking policies</a></li>
</ul>
<h2><a name="headers">Header summary</a></h2>
<p>
Boost.Flyweight comprises the following public headers:
<ul>
<li><a href="#flyweight_synopsis"><code>"boost/flyweight.hpp"</code></a></li>
<li>Class template <code>flyweight</code>
<ul>
<li><a href="flyweight.html#flyweight_fwd_synopsis"><code>"boost/flyweight/flyweight_fwd.hpp"</code></a></li>
<li><a href="flyweight.html#synopsis"><code>"boost/flyweight/flyweight.hpp"</code></a></li>
</ul>
</li>
<li>Key-value flyweights
<ul>
<li><a href="key_value.html#key_value_fwd_synopsis"><code>"boost/flyweight/key_value_fwd.hpp"</code></a></li>
<li><a href="key_value.html#synopsis"><code>"boost/flyweight/key_value.hpp"</code></a></li>
</ul>
</li>
<li>Tags
<ul>
<li><a href="tags.html#tag_synopsis"><code>"boost/flyweight/tag.hpp"</code></a></li>
</ul>
</li>
<li>Factories
<ul>
<li><a href="factories.html#factory_tag_synopsis"><code>"boost/flyweight/factory_tag.hpp"</code></a></li>
<li><a href="factories.html#hashed_factory_fwd_synopsis"><code>"boost/flyweight/hashed_factory_fwd.hpp"</code></a></li>
<li><a href="factories.html#hashed_factory_synopsis"><code>"boost/flyweight/hashed_factory.hpp"</code></a></li>
<li><a href="factories.html#set_factory_fwd_synopsis"><code>"boost/flyweight/set_factory_fwd.hpp"</code></a></li>
<li><a href="factories.html#set_factory_synopsis"><code>"boost/flyweight/set_factory.hpp"</code></a></li>
<li><a href="factories.html#assoc_container_factory_fwd_synopsis"><code>"boost/flyweight/assoc_container_factory_fwd.hpp"</code></a></li>
<li><a href="factories.html#assoc_container_factory_synopsis"><code>"boost/flyweight/assoc_container_factory.hpp"</code></a></li>
</ul>
</li>
<li>Holders
<ul>
<li><a href="holders.html#holder_tag_synopsis"><code>"boost/flyweight/holder_tag.hpp"</code></a></li>
<li><a href="holders.html#static_holder_fwd_synopsis"><code>"boost/flyweight/static_holder_fwd.hpp"</code></a></li>
<li><a href="holders.html#static_holder_synopsis"><code>"boost/flyweight/static_holder.hpp"</code></a></li>
<li><a href="holders.html#intermodule_holder_fwd_synopsis"><code>"boost/flyweight/intermodule_holder_fwd.hpp"</code></a></li>
<li><a href="holders.html#intermodule_holder_synopsis"><code>"boost/flyweight/intermodule_holder.hpp"</code></a></li>
</ul>
</li>
<li>Locking policies
<ul>
<li><a href="locking.html#locking_tag_synopsis"><code>"boost/flyweight/locking_tag.hpp"</code></a></li>
<li><a href="locking.html#simple_locking_fwd_synopsis"><code>"boost/flyweight/simple_locking_fwd.hpp"</code></a></li>
<li><a href="locking.html#simple_locking_synopsis"><code>"boost/flyweight/simple_locking.hpp"</code></a></li>
<li><a href="locking.html#no_locking_fwd_synopsis"><code>"boost/flyweight/no_locking_fwd.hpp"</code></a></li>
<li><a href="locking.html#no_locking_synopsis"><code>"boost/flyweight/no_locking.hpp"</code></a></li>
</ul>
</li>
<li>Tracking policies
<ul>
<li><a href="tracking.html#tracking_tag_synopsis"><code>"boost/flyweight/tracking_tag.hpp"</code></a></li>
<li><a href="tracking.html#refcounted_fwd_synopsis"><code>"boost/flyweight/refcounted_fwd.hpp"</code></a></li>
<li><a href="tracking.html#refcounted_synopsis"><code>"boost/flyweight/refcounted.hpp"</code></a></li>
<li><a href="tracking.html#no_tracking_fwd_synopsis"><code>"boost/flyweight/no_tracking_fwd.hpp"</code></a></li>
<li><a href="tracking.html#no_tracking_synopsis"><code>"boost/flyweight/no_tracking.hpp"</code></a></li>
</ul>
</li>
</ul>
</p>
<p>
Boost.Flyweight is a header-only library, requiring no additional
object modules.
</p>
<h2>
<a name="flyweight_synopsis">Header
<a href="../../../../boost/flyweight.hpp"><code>"boost/flyweight.hpp"</code></a>
synopsis</a>
</h2>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>hashed_factory</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>refcounted</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>simple_locking</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>static_holder</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
</pre></blockquote>
<p>
This convenience header includes the main class template
<a href="flyweight.html#flyweight"><code>flyweight</code></a> along with
the default components used by <code>flyweight</code>.
</p>
<hr>
<div class="prev_link"><a href="../tutorial/lambda_expressions.html"><img src="../prev.gif" alt="annex: MPL lambda expressions" border="0"><br>
Annex: MPL lambda expressions
</a></div>
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="flyweight.html"><img src="../next.gif" alt="flyweight reference" border="0"><br>
<code>flyweight</code> reference
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised December 2nd 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

View File

@@ -0,0 +1,124 @@
<!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 - Key-value flyweights reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="flyweight.html">
<link rel="up" href="index.html">
<link rel="next" href="tags.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Key-value flyweights reference</h1>
<div class="prev_link"><a href="flyweight.html"><img src="../prev.gif" alt="flyweight reference" border="0"><br>
<code>flyweight</code> reference
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="tags.html"><img src="../next.gif" alt="tags" border="0"><br>
Tags
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#key_extractor">Key extractors</a></li>
<li><a href="#key_value_fwd_synopsis">Header
<code>"boost/flyweight/key_value_fwd.hpp"</code> synopsis</a>
</li>
<li><a href="#synopsis">Header
<code>"boost/flyweight/key_value.hpp"</code> synopsis</a>
<ul>
<li><a href="#key_value_construct">Class template <code>key_value</code></a></li>
</ul>
</li>
</ul>
<h2><a name="key_extractor">Key extractors</a></h2>
<p>
Let <code>Key</code> be a type with some implicit equivalence relationship
and <code>Value</code> a type constructible from <code>Key</code>.
A <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"><code>Default
Constructible</code></a> type <code>KeyFromValue</code> is said
to be a key extractor from <code>Value</code> to <code>Key</code> if
<ol>
<li><code>kfv(cv)</code> is defined and have type <code>const Key&amp;</code>,</li>
<li><code>kfv(cv)</code> is equivalent to <code>kfv(Value(cv))</code>,</li>
<li><code>kfv(Value(k))</code> is equivalent to <code>k</code>,</li>
</ol>
for every <code>kfv</code> of type <code>const KeyFromValue</code>,
<code>cv</code> of type <code>const Value</code> and
<code>k</code> of type <code>Key</code>.
</p>
<h2><a name="key_value_fwd_synopsis">Header
<a href="../../../../boost/flyweight/key_value_fwd.hpp"><code>"boost/flyweight/key_value_fwd.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>struct</span> <span class=identifier>no_key_from_value</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>KeyFromValue</span><span class=special>=</span><span class=identifier>no_key_from_value</span>
<span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>key_value</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<h2><a name="synopsis">Header
<a href="../../../../boost/flyweight/key_value.hpp"><code>"boost/flyweight/key_value.hpp"</code></a> synopsis</a></h2>
<h3><a name="key_value_construct">Class template <code>key_value</code></a></h3>
<p>
In <a href="flyweight.html#flyweight"><code>flyweight</code></a> instantiations
of the form <code>flyweight&lt;T,...&gt;</code>, the associated
<code>key_type</code> and <code>value_type</code> are both equal to <code>T</code>.
Instantiations of the form <code>flyweight&lt;key_value&lt;Key,Value[,KeyFromValue]&gt;,...&gt;</code>
allow to specify these types separately. <code>Key</code> and <code>Value</code>
must be different types. When provided, <code>KeyFromValue</code>
must be a <a href="#key_extractor"><code>Key Extractor</code></a> from
<code>Value</code> to <code>Key</code>.
</p>
<hr>
<div class="prev_link"><a href="flyweight.html"><img src="../prev.gif" alt="flyweight reference" border="0"><br>
<code>flyweight</code> reference
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="tags.html"><img src="../next.gif" alt="tags" border="0"><br>
Tags
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised September 15th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

287
doc/reference/locking.html Normal file
View File

@@ -0,0 +1,287 @@
<!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 - Locking policies reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="factories.html">
<link rel="up" href="index.html">
<link rel="next" href="tracking.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight
Locking policies reference</h1>
<div class="prev_link"><a href="holders.html"><img src="../prev.gif" alt="holders" border="0"><br>
Holders
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="tracking.html"><img src="../next.gif" alt="tracking policies" border="0"><br>
Tracking policies
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#preliminary">Preliminary concepts</a></li>
<li><a href="#locking">Locking policies</a></li>
<li><a href="#locking_tag_synopsis">Header
<code>"boost/flyweight/locking_tag.hpp"</code> synopsis</a>
<ul>
<li><a href="#is_locking">Class template <code>is_locking</code></a></li>
<li><a href="#locking_construct">Class template <code>locking</code></a></li>
</ul>
</li>
<li><a href="#simple_locking_fwd_synopsis">Header
<code>"boost/flyweight/simple_locking_fwd.hpp"</code> synopsis</a>
</li>
<li><a href="#simple_locking_synopsis">Header
<code>"boost/flyweight/simple_locking.hpp"</code> synopsis</a>
<ul>
<li><a href="#simple_locking">Class <code>simple_locking</code></a></li>
</ul>
</li>
<li><a href="#no_locking_fwd_synopsis">Header
<code>"boost/flyweight/no_locking_fwd.hpp"</code> synopsis</a>
</li>
<li><a href="#no_locking_synopsis">Header
<code>"boost/flyweight/no_locking.hpp"</code> synopsis</a>
<ul>
<li><a href="#no_locking">Class <code>no_locking</code></a></li>
</ul>
</li>
</ul>
<h2><a name="preliminary">Preliminary concepts</a></h2>
<p>
A <i>mutex</i> is a type whose objects can be in either of two states, called
locked and unlocked, with the property that when a thread A has locked a
mutex <code>m</code> and a different thread B tries to lock <code>m</code>,
B is blocked until A unlocks <code>m</code>. Additionally, a mutex is said to
support <i>recursive locking</i> if a thread can succesfully invoke the locking
operation for a mutex already locked by this same thread; in this case, it is
required that the thread execute as many unlock operations as lock
operations it has performed for the mutex to become effectively unlocked.
A <i>scoped lock</i> is a
type associated to some mutex type whose objects do the locking/unlocking
of a mutex on construction/destruction time.
</p>
<p>
In the following table, <code>Mutex</code> is a mutex type, <code>m</code>
is an object of type <code>Mutex</code>, <code>Lock</code> is a scoped lock
associated to <code>Mutex</code> and <code>lk</code> is a value of
<code>Lock</code>.
<p align="center">
<table cellspacing="0">
<caption><b>Mutex and Scoped Lock requirements.</b></caption>
<tr>
<th align="center">expression</th>
<th align="center">return type</th>
<th align="center">assertion/note<br>pre/post-condition</th>
</tr>
<tr>
<td><code>Mutex m;</code></td>
<td>&nbsp;</td>
<td>Post: <code>m</code> is unlocked.
</td>
</tr>
<tr class="odd_tr">
<td><code>(&amp;m)->~Mutex();</code></td>
<td><code>void</code></td>
<td>Pre: <code>m</code> is unlocked.</td>
</tr>
<tr>
<td><code>Lock lk(m);</code></td>
<td>&nbsp;</td>
<td>Associates <code>m</code> to <code>lk</code> and locks <code>m</code>.</td>
</tr>
<tr class="odd_tr">
<td><code>(&amp;lk)->~Lock();</code></td>
<td><code>void</code></td>
<td>Unlocks the mutex associated to <code>lk</code>.</td>
</tr>
</table>
</p>
<p>
These concepts are very similar, but not entirely equivalent, to
the homonym ones described in the
<a href="../../../../doc/html/thread/concepts.htm">Boost Thread
Library</a>.
</p>
<h2><a name="locking">Locking policies</a></h2>
<p>
<i>Locking policies</i> describe a mutex type and an associated
scoped lock type.
<a href="flyweight.html#flyweight"><code>flyweight</code></a> uses a given locking
policy to synchronize the access to its internal
<a href="factories.html#factory">factory</a>.
</p>
<p>
A type <code>Locking</code> is a locking policy if:
<ul>
<li>One of the following conditions is satisfied:
<ol type="a">
<li><a href="#is_locking"><code>is_locking&lt;Locking&gt;::type</code></a> is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::true_</code></a>,</li>
<li><code>Locking</code> is of the form
<a href="#tracking_construct"><code>locking&lt;Locking'&gt;</code></a>.</li>
</ol>
</li>
<li>The type <code>Locking::mutex_type</code> (or
<code>Locking'::mutex_type</code> if (b) applies) is a
model of <a href="#preliminary"><code>Mutex</code></a>
and supports recursive locking.
</li>
<li>The type <code>Locking::lock_type</code> (or
<code>Locking'::lock_type</code> if (b) applies) is a
<a href="#preliminary"><code>Scoped Lock</code></a> of
the mutex referred to above.
</li>
</ul>
</p>
<h2><a name="locking_tag_synopsis">Header
<a href="../../../../boost/flyweight/locking_tag.hpp"><code>"boost/flyweight/locking_tag.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>struct</span> <span class=identifier>locking_marker</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>is_locking</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>locking</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<h3><a name="is_locking">Class template <code>is_locking</code></a></h3>
<p>
Unless specialized by the user, <code>is_locking&lt;T&gt;::type</code> is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::true_</code></a>
if <code>T</code> is derived from <code>locking_marker</code>, and it is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::false_</code></a>
otherwise.
</p>
<h3><a name="locking_construct">Class template <code>locking</code></a></h3>
<p>
<code>locking&lt;T&gt;</code> is a syntactic construct meant to indicate
that <code>T</code> is a locking policy without resorting to the
mechanisms provided by the <code>is_locking</code> class template.
</p>
<h2><a name="simple_locking_fwd_synopsis">Header
<a href="../../../../boost/flyweight/simple_locking_fwd.hpp"><code>"boost/flyweight/simple_locking_fwd.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>struct</span> <span class=identifier>simple_locking</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
<code>simple_locking_fwd.hpp</code> forward declares the class
<a href="#simple_locking"><code>simple_locking</code></a>.
</p>
<h2><a name="simple_locking_synopsis">Header
<a href="../../../../boost/flyweight/simple_locking.hpp"><code>"boost/flyweight/simple_locking.hpp"</code></a> synopsis</a></h2>
<h3><a name="simple_locking">Class <code>simple_locking</code></a></h3>
<p>
<a href="#locking"><code>Locking Policy</code></a> that specifies a basic
mutex type based on the simplest synchronization mechanisms provided by
the environment; When no threading capabilities are available,
<code>simple_locking</code> specifies a dummy type without actual
synchronization capabilities.
</p>
<h2><a name="no_locking_fwd_synopsis">Header
<a href="../../../../boost/flyweight/no_locking_fwd.hpp"><code>"boost/flyweight/no_locking_fwd.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>struct</span> <span class=identifier>no_locking</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
<code>no_locking_fwd.hpp</code> forward declares the class
<a href="#no_locking"><code>no_locking</code></a>.
</p>
<h2><a name="no_locking_synopsis">Header
<a href="../../../../boost/flyweight/no_locking.hpp"><code>"boost/flyweight/no_locking.hpp"</code></a> synopsis</a></h2>
<h3><a name="no_locking">Class <code>no_locking</code></a></h3>
<p>
Null <a href="#locking"><code>Locking Policy</code></a>: it specifies a dummy
type that satisfies the formal requirements for the
<a href="#preliminary"><code>Mutex</code></a> concept but does not perform
thread blocking. <code>no_locking</code> should only be used in single-threaded
environments.
</p>
<hr>
<div class="prev_link"><a href="holders.html"><img src="../prev.gif" alt="holders" border="0"><br>
Holders
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="tracking.html"><img src="../next.gif" alt="tracking policies" border="0"><br>
Tracking policies
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised August 13th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

107
doc/reference/tags.html Normal file
View File

@@ -0,0 +1,107 @@
<!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 - Tags reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="key_value.html">
<link rel="up" href="index.html">
<link rel="next" href="factories.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight
Tags reference</h1>
<div class="prev_link"><a href="key_value.html"><img src="../prev.gif" alt="key-value flyweights" border="0"><br>
Key-value flyweights
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="factories.html"><img src="../next.gif" alt="factories" border="0"><br>
Factories
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#tag">Tags</a></li>
<li><a href="#tag_synopsis">Header
<code>"boost/flyweight/tag.hpp"</code> synopsis</a>
<ul>
<li><a href="#tag_construct">Class template <code>tag</code></a></li>
</ul>
</li>
</ul>
<h2><a name="tag">Tags</a></h2>
<p>
A <i>tag</i> is a type of the form
<a href="#tag_construct"><code>tag&lt;T&gt;</code></a> for some arbitrary
<code>T</code>.
In the context of Boost.Flyweight, tags are syntactic artifacts used
to differentiate instantiations of the class template
<a href="flyweight.html#flyweight"><code>flyweight</code></a> which would
otherwise be identical. Tagging a <code>flyweight</code> instantiation with
a tag type local to a given context ensures that the global resources
of that instantiation (for instance, the associated
<a href="factories.html#factory">factory class</a>) will not be unintentionally
shared by other areas of the program.
</p>
<h2><a name="tag_synopsis">Header
<a href="../../../../boost/flyweight/tag.hpp"><code>"boost/flyweight/tag.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>tag</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<h3><a name="tag_construct">Class template <code>tag</code></a></h3>
<p>
For any type <code>T</code>, <code>tag&lt;T&gt;</code> is a suitable
<a href="#tag">tag</a> for use in instantiations of
<a href="flyweight.html#flyweight"><code>flyweight</code></a>.
</p>
<hr>
<div class="prev_link"><a href="key_value.html"><img src="../prev.gif" alt="key-value flyweights" border="0"><br>
Key-value flyweights
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="factories.html"><img src="../next.gif" alt="factories" border="0"><br>
Factories
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised August 11th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

291
doc/reference/tracking.html Normal file
View File

@@ -0,0 +1,291 @@
<!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 - Tracking policies reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="locking.html">
<link rel="up" href="index.html">
<link rel="next" href="../performance.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight
Tracking policies reference</h1>
<div class="prev_link"><a href="locking.html"><img src="../prev.gif" alt="locking policies" border="0"><br>
Locking policies
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="../performance.html"><img src="../next.gif" alt="performance" border="0"><br>
Performance
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#preliminary">Preliminary concepts</a></li>
<li><a href="#tracking">Tracking policies</a></li>
<li><a href="#tracking_tag_synopsis">Header
<code>"boost/flyweight/tracking_tag.hpp"</code> synopsis</a>
<ul>
<li><a href="#is_tracking">Class template <code>is_tracking</code></a></li>
<li><a href="#tracking_construct">Class template <code>tracking</code></a></li>
</ul>
</li>
<li><a href="#refcounted_fwd_synopsis">Header
<code>"boost/flyweight/refcounted_fwd.hpp"</code> synopsis</a>
</li>
<li><a href="#refcounted_synopsis">Header
<code>"boost/flyweight/refcounted.hpp"</code> synopsis</a>
<ul>
<li><a href="#refcounted">Class <code>refcounted</code></a></li>
</ul>
</li>
<li><a href="#no_tracking_fwd_synopsis">Header
<code>"boost/flyweight/no_tracking_fwd.hpp"</code> synopsis</a>
</li>
<li><a href="#no_tracking_synopsis">Header
<code>"boost/flyweight/no_tracking.hpp"</code> synopsis</a>
<ul>
<li><a href="#no_tracking">Class <code>no_tracking</code></a></li>
</ul>
</li>
</ul>
<h2><a name="preliminary">Preliminary concepts</a></h2>
<p>
A <i>tracking policy helper</i> provides access to some of the functionality
of a <a href="factories.html#factory">factory</a> so as to be used
in the implementation of an associated <a href="#tracking"><code>Tracking Policy</code></a>.
In the following table, <code>TrackingHelper</code> is a tracking policy
helper associated to a <a href="factories.html#factory">factory</a> type
<code>Factory</code> of elements of type <code>Entry</code>, <code>h</code>
is a value of
<code>Factory::handle_type</code> associated to a <code>Factory</code> <code>f</code>
and <code>check</code> is a value of
a <a href="http://www.sgi.com/tech/stl/Predicate.html"><code>Predicate</code></a>
type <code>Checker</code> with argument of type <code>Factory::handle_type</code>.
</p>
<p align="center">
<table cellspacing="0">
<caption><b>Tracking Policy Helper requirements.</b></caption>
<tr>
<th align="center">expression</th>
<th align="center">return type</th>
<th align="center">assertion/note<br>pre/post-condition</th>
</tr>
<tr>
<td><code>TrackingHelper::entry(h);</code></td>
<td><code>const Entry&amp;</code></td>
<td>Returns <code>f.entry(h)</code>.</td>
</tr>
<tr class="odd_tr">
<td><code>TrackingHelper::erase(h,check);</code></td>
<td><code>void</code></td>
<td>If <code>check(h)</code>, invokes <code>f.erase(h)</code>.</td>
</tr>
</table>
</p>
<p>
The execution of <code>TrackingHelper::erase</code> (including the
invocation of <code>check(h)</code>) is done in a
synchronized manner so as to prevent any other thread of execution from
simultaneously accessing the factory's insertion or deletion facilities.
</p>
<h2><a name="tracking">Tracking policies</a></h2>
<p>
A <i>tracking policy</i> defines the strategy to be followed by a
<a href="flyweight.html#flyweight"><code>flyweight</code></a> instantiation when
all the flyweight objects associated to a given value are destroyed.
The tracking policy contributes some type information necessary for the
definition of the <code>flyweight</code> internal
<a href="factories.html#factory">factory</a>.
</p>
<p>
A type <code>Tracking</code> is a tracking policy if:
<ul>
<li>One of the following conditions is satisfied:
<ol type="a">
<li><a href="#is_tracking"><code>is_tracking&lt;Tracking&gt;::type</code></a> is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::true_</code></a>,</li>
<li><code>Tracking</code> is of the form
<a href="#tracking_construct"><code>tracking&lt;Tracking'&gt;</code></a>.</li>
</ol>
</li>
<li>The expression <code>Tracking::entry_type</code> (or
<code>Tracking'::entry_type</code> if (b) applies) is an
<a href="../../../mpl/doc/refmanual/lambda-expression.html"><code>MPL Lambda
Expression</code></a> that resolves, when invoked with different types
(<code>Value</code>,<code>Key</code>) such that <code>Value</code> is
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
and implicitly convertible to <code>const Key&amp;</code>, to an
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
type <code>Entry</code> implicitly convertible to both <code>const Value&amp;</code>
and <code>const Key&amp;</code>.
</li>
<li>The expression <code>Tracking::handle_type</code> (or
<code>Tracking'::handle_type</code> if (b) applies) is an
<a href="../../../mpl/doc/refmanual/lambda-expression.html"><code>MPL Lambda
Expression</code></a>; this expression, when invoked with types
(<code>InternalHandle</code>,<a href="#preliminary"><code>TrackingHelper</code></a>),
with <code>InternalHandle</code> being
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
and providing the nothrow guarantee for copy and assignment,
resolves to an
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
type <code>Handle</code> which also provides the nothrow guarantee for
copy and assignment and is constructible from and implicitly
convertible to <code>InternalHandle</code>.
<code>TrackingHelper</code> is an incomplete type at the time of
invocation of <code>Tracking::handle_type</code>.
</li>
</ul>
<code>Tracking::handle_type</code> is parameterized by a helper that provides
access to some of the functionality of the factory associated to the
tracking policy. This factory's associated entry and handle types are the types
<code>Entry</code> and <code>Handle</code> defined above, respectively.
</p>
<h2><a name="tracking_tag_synopsis">Header
<a href="../../../../boost/flyweight/tracking_tag.hpp"><code>"boost/flyweight/tracking_tag.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>struct</span> <span class=identifier>tracking_marker</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>is_tracking</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>tracking</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<h3><a name="is_tracking">Class template <code>is_tracking</code></a></h3>
<p>
Unless specialized by the user, <code>is_tracking&lt;T&gt;::type</code> is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::true_</code></a>
if <code>T</code> is derived from <code>tracking_marker</code>, and it is
<a href="../../../mpl/doc/refmanual/bool.html"><code>boost::mpl::false_</code></a>
otherwise.
</p>
<h3><a name="tracking_construct">Class template <code>tracking</code></a></h3>
<p>
<code>tracking&lt;T&gt;</code> is a syntactic construct meant to indicate
that <code>T</code> is a tracking policy without resorting to the
mechanisms provided by the <code>is_tracking</code> class template.
</p>
<h2><a name="refcounted_fwd_synopsis">Header
<a href="../../../../boost/flyweight/refcounted_fwd.hpp"><code>"boost/flyweight/refcounted_fwd.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>struct</span> <span class=identifier>refcounted</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
<code>refcounted_fwd.hpp</code> forward declares the class
<a href="#refcounted"><code>refcounted</code></a>.
</p>
<h2><a name="refcounted_synopsis">Header
<a href="../../../../boost/flyweight/refcounted.hpp"><code>"boost/flyweight/refcounted.hpp"</code></a> synopsis</a></h2>
<h3><a name="refcounted">Class <code>refcounted</code></a></h3>
<p>
<a href="#tracking"><code>Tracking Policy</code></a> providing
<a href="flyweight.html#flyweight"><code>flyweight</code></a>
instantiations with reference counting semantics: when all the flyweight objects
associated to a given value are destroyed, the corresponding entry is
erased from <code>flyweight</code>'s internal
<a href="factories.html#factory">factory</a>.
</p>
<h2><a name="no_tracking_fwd_synopsis">Header
<a href="../../../../boost/flyweight/no_tracking_fwd.hpp"><code>"boost/flyweight/no_tracking_fwd.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<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>struct</span> <span class=identifier>no_tracking</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::flyweights</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
<code>no_tracking_fwd.hpp</code> forward declares the class
<a href="#no_tracking"><code>no_tracking</code></a>.
</p>
<h2><a name="no_tracking_synopsis">Header
<a href="../../../../boost/flyweight/no_tracking.hpp"><code>"boost/flyweight/no_tracking.hpp"</code></a> synopsis</a></h2>
<h3><a name="no_tracking">Class <code>no_tracking</code></a></h3>
<p>
Null <a href="#tracking"><code>Tracking Policy</code></a>: elements inserted
into <code>flyweight</code>'s internal <a href="factories.html#factory">factory</a>
are not erased until program termination.
</p>
<hr>
<div class="prev_link"><a href="locking.html"><img src="../prev.gif" alt="locking policies" border="0"><br>
Locking policies
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div>
<div class="next_link"><a href="../performance.html"><img src="../next.gif" alt="performance" border="0"><br>
Performance
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised August 18th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

70
doc/release_notes.html Normal file
View File

@@ -0,0 +1,70 @@
<!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 - Release notes</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="future_work.html">
<link rel="up" href="index.html">
<link rel="next" href="acknowledgements.html">
</head>
<body>
<h1><img src="../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Release notes</h1>
<div class="prev_link"><a href="future_work.html"><img src="prev.gif" alt="future work" border="0"><br>
Future work
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="acknowledgements.html"><img src="next.gif" alt="acknowledgements" border="0"><br>
Acknowledgements
</a></div><br clear="all" style="clear: all;">
<br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#boost_1_38">Boost 1.38 release</a></li>
</ul>
<h2><a name="boost_1_38">Boost 1.38 release</a></h2>
<p>
<ul>
<li>Initial release of Boost.Flyweight.</li>
</ul>
</p>
<hr>
<div class="prev_link"><a href="future_work.html"><img src="prev.gif" alt="future work" border="0"><br>
Future work
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="acknowledgements.html"><img src="next.gif" alt="acknowledgements" border="0"><br>
Acknowledgements
</a></div><br clear="all" style="clear: all;">
<br clear="all" style="clear: all;">
<br>
<p>Revised August 27th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

54
doc/style.css Normal file
View File

@@ -0,0 +1,54 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
pre{
BORDER-RIGHT: gray 1pt solid;
PADDING-RIGHT: 2pt;
BORDER-TOP: gray 1pt solid;
DISPLAY: block;
PADDING-LEFT: 2pt;
PADDING-BOTTOM: 2pt;
BORDER-LEFT: gray 1pt solid;
MARGIN-RIGHT: 32pt;
PADDING-TOP: 2pt;
BORDER-BOTTOM: gray 1pt solid;
FONT-FAMILY: "Courier New", Courier, mono;
background-color: #EEEEEE;
}
table{
PADDING-RIGHT: 2pt;
BORDER-TOP: gray 1pt solid;
DISPLAY: block;
PADDING-LEFT: 2pt;
PADDING-BOTTOM: 2pt;
BORDER-LEFT: gray 1pt solid;
MARGIN-RIGHT: 32pt;
PADDING-TOP: 2pt;
background-color: #EEEEEE;
}
td{
BORDER-STYLE: solid;
BORDER-WIDTH: 1pt;
BORDER-LEFT: ;
BORDER-RIGHT: gray 1pt solid;
BORDER-TOP: ;
BORDER-BOTTOM: gray 1pt solid;
}
th{color: #ffffff; background-color: #000000;}
.odd_tr{background-color: #ffffff;}
.keyword{color: #0000FF;}
.identifier{}
.comment{font-style: italic; color: #008000;}
.special{color: #800040;}
.preprocessor{color: #3F007F;}
.string{font-style: italic; color: #666666;}
.literal{font-style: italic; color: #666666;}
.prev_link{width: 30%; float: left; text-align: left;}
.up_link{width: 39.9%; float: left; text-align: center;}
.next_link{width: 30%; float: left; text-align: right;}

114
doc/tests.html Normal file
View File

@@ -0,0 +1,114 @@
<!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 - Tests</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="examples.html">
<link rel="up" href="index.html">
<link rel="next" href="future_work.html">
</head>
<body>
<h1><img src="../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Tests</h1>
<div class="prev_link"><a href="examples.html"><img src="prev.gif" alt="examples" border="0"><br>
Examples
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="future_work.html"><img src="next.gif" alt="future work" border="0"><br>
Future work
</a></div><br clear="all" style="clear: all;">
<hr>
<p>
The Boost.Flyweight test suite exercises the whole spectrum of
functionalities provided by the library. Although the tests are not meant
to serve as a learning guide, the interested reader may find it
useful to inspect the source code to gain familiarity with the usage
of Boost.Flyweight.
</p>
<p align="center">
<table cellspacing="0" cellpadding="5">
<caption><b>Boost.Flyweight test suite.</b></caption>
<tr>
<th>Program</th>
<th>Description</th>
</tr>
<tr>
<td><a href="../test/test_assoc_cont_factory.cpp"><code>test_assoc_cont_factory.cpp</code></a></td>
<td><a href="tutorial/configuration.html#assoc_container_factory"><code>assoc_container_factory</code></a>
factory specifier.</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_basic.cpp"><code>test_basic.cpp</code></a></td>
<td>Exercises the default components of <code>flyweight</code>.</td>
</tr>
<tr>
<td><a href="../test/test_custom_factory.cpp"><code>test_custom_factory.cpp</code></a></td>
<td>Creates a user-defined factory class and specifier.</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_init.cpp"><code>test_init.cpp</code></a></td>
<td>Boost.Flyweight <a href="tutorial/technical.html#static_init">static
data initialization</a> facilities.</td>
</tr>
<tr>
<td><a href="../test/test_intermod_holder.cpp"><code>test_intermod_holder.cpp</code></a><br>
<a href="../test/intermod_holder_dll.cpp"><code>intermod_holder_dll.cpp</code></a></td>
<td>Exercises <a href="tutorial/configuration.html#intermodule_holder"><code>intermodule_holder</code></a>.</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_multictor.cpp"><code>test_multictor.cpp</code></a></td>
<td>Tests <code>flyweight</code> <a href="reference/flyweight.html#constructors">multiple
argument constructors</a>.</td>
</tr>
<tr>
<td><a href="../test/test_no_locking.cpp"><code>test_no_locking.cpp</code></a></td>
<td><a href="tutorial/configuration.html#no_locking"><code>no_locking</code></a> policy.</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_no_tracking.cpp"><code>test_no_tracking.cpp</code></a></td>
<td><a href="tutorial/configuration.html#no_tracking"><code>no_tracking</code></a> policy.</td>
</tr>
<tr>
<td><a href="../test/test_set_factory.cpp"><code>test_set_factory.cpp</code></a></td>
<td><a href="tutorial/configuration.html#set_factory"><code>set_factory</code></a>
factory specifier.</td>
</tr>
</table>
</p>
<hr>
<div class="prev_link"><a href="examples.html"><img src="prev.gif" alt="examples" border="0"><br>
Examples
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="future_work.html"><img src="next.gif" alt="future work" border="0"><br>
Future work
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised December 2nd 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

BIN
doc/time_gcc_344.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
doc/time_msvc_80.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

227
doc/tutorial/basics.html Normal file
View File

@@ -0,0 +1,227 @@
<!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 - Basics</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="index.html">
<link rel="up" href="index.html">
<link rel="next" href="key_value.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Tutorial: Basics</h1>
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.Flyweight tutorial" border="0"><br>
Boost.Flyweight tutorial
</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="key_value.html"><img src="../next.gif" alt="key-value flyweights" border="0"><br>
Key-value flyweights
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#requirements">Flyweight requirements</a></li>
</ul>
<h2><a name="intro">Introduction</a></h2>
<p>
Suppose we are writing a massive multiplayer online game
which has to maintain hundreds of thousands or millions of instances
of the following class in memory:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>user_entry</span>
<span class=special>{</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>first_name</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>last_name</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>age</span><span class=special>;</span>
<span class=special>...</span>
<span class=special>};</span>
</pre></blockquote>
<p>
In this kind of environments memory resources are precious, so we are seeking
ways to make <code>user_entry</code> as compact as possible. Typically, there
exists a very high level of repetition of first and last names among
the community users, so an obvious optimization consists in moving
<code>user_entry::first_name</code> and <code>user_entry::last_name</code>
objects to a common repository where duplicates are avoided, and leaving
references to these inside <code>user_entry</code>. This is precisely what
Boost.Flyweight does in the simplest possible way for the programmer:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>user_entry</span>
<span class=special>{</span>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=identifier>first_name</span><span class=special>;</span>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=identifier>last_name</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>age</span><span class=special>;</span>
<span class=special>...</span>
<span class=special>};</span>
</pre></blockquote>
<p>
Boost.Flyweight automatically performs the optimization just described behind
the scenes, so that the net effect of this change is that the memory
usage of the program decreases by a factor proportional to the level of
redundancy among user names.
</p>
<p>
<code>flyweight&lt;std::string&gt;</code> behaves in many ways like
<code>std::string</code>; for instance, the following code works
unchanged after the redefinition of <code>user_entry</code>:
</p>
<blockquote><pre>
<span class=comment>// flyweight&lt;T&gt; can be constructed in the same way as T objects can,
// even with multiple argument constructors</span>
<span class=identifier>user_entry</span><span class=special>::</span><span class=identifier>user_entry</span><span class=special>(</span><span class=keyword>const</span> <span class=keyword>char</span><span class=special>*</span> <span class=identifier>f</span><span class=special>,</span><span class=keyword>const</span> <span class=keyword>char</span><span class=special>*</span> <span class=identifier>l</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>a</span><span class=special>,...):</span>
<span class=identifier>first_name</span><span class=special>(</span><span class=identifier>f</span><span class=special>),</span>
<span class=identifier>last_name</span><span class=special>(</span><span class=identifier>l</span><span class=special>),</span>
<span class=identifier>age</span><span class=special>(</span><span class=identifier>a</span><span class=special>),</span>
<span class=special>...</span>
<span class=special>{}</span>
<span class=comment>// flyweight classes have relational operators replicating the
// semantics of the underyling type</span>
<span class=keyword>bool</span> <span class=identifier>same_name</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user1</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user2</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>user1</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>==</span><span class=identifier>user2</span><span class=special>.</span><span class=identifier>first_name</span> <span class=special>&amp;&amp;</span>
<span class=identifier>user1</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>==</span><span class=identifier>user2</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>;</span>
<span class=special>}</span>
<span class=comment>// flyweight&lt;T&gt; provides operator&lt;&lt; and operator&gt;&gt; internally
// forwarding to T::operator&lt;&lt; and T::operator&gt;&gt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>&lt;&lt;(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream</span><span class=special>&amp;</span> <span class=identifier>os</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>os</span><span class=special>&lt;&lt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>&lt;&lt;</span><span class=string>&quot; &quot;</span><span class=special>&lt;&lt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>&lt;&lt;</span><span class=string>&quot; &quot;</span><span class=special>&lt;&lt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>age</span><span class=special>;</span>
<span class=special>}</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>istream</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>&gt;&gt;(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>istream</span><span class=special>&amp;</span> <span class=identifier>is</span><span class=special>,</span><span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>is</span><span class=special>&gt;&gt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>&gt;&gt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>&gt;&gt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>age</span><span class=special>;</span>
<span class=special>}</span>
</pre></blockquote>
<p>
Besides, <code>flyweight&lt;T&gt;</code> is convertible to
<code>const T&amp;</code>, either implicitly or through the <code>get</code>
member function:
</p>
<blockquote><pre>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>full_name</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user</span><span class=special>)</span>
<span class=special>{</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>full</span><span class=special>;</span>
<span class=identifier>full</span><span class=special>.</span><span class=identifier>reserve</span><span class=special>(</span>
<span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>.</span><span class=identifier>get</span><span class=special>().</span><span class=identifier>size</span><span class=special>()+</span> <span class=comment>// get() returns the underlying</span>
<span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>.</span><span class=identifier>get</span><span class=special>().</span><span class=identifier>size</span><span class=special>()+</span><span class=number>1</span><span class=special>);</span> <span class=comment>// const std::string&amp;</span>
<span class=identifier>full</span><span class=special>+=</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>;</span> <span class=comment>// implicit conversion is used here</span>
<span class=identifier>full</span><span class=special>+=</span><span class=string>&quot; &quot;</span><span class=special>;</span>
<span class=identifier>full</span><span class=special>+=</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>;</span>
<span class=keyword>return</span> <span class=identifier>full</span><span class=special>;</span>
<span class=special>}</span>
</pre></blockquote>
<p>
The most important restriction to take into account when replacing a class
with an equivalent flyweight is the fact that flyweights are not
mutable: since several flyweight objects can share the same representation
value, modifying this value is not admissible. On the other hand, flyweight
objects can be assigned new values:
</p>
<blockquote><pre>
<span class=keyword>void</span> <span class=identifier>change_name</span><span class=special>(</span>
<span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=identifier>f</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=identifier>l</span><span class=special>)</span>
<span class=special>{</span>
<span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>=</span><span class=identifier>f</span><span class=special>;</span>
<span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>=</span><span class=identifier>l</span><span class=special>;</span>
<span class=special>}</span>
</pre></blockquote>
<p>
In general, <code>flyweight&lt;T&gt;</code> interface is designed to make
the transition from plain <code>T</code> as straightforward as possible.
Check the <a href="../reference/flyweight.html#flyweight">reference</a> for
further details on the interface of the class template <code>flyweight</code>.
The <a href="../examples.html">examples section</a> explores
some common usage scenarios of Boost.Flyweight.
</p>
<h3><a name="requirements">Flyweight requirements</a></h3>
<p>
For <code>flyweight&lt;T&gt;</code> to be instantiable, <code>T</code> must
be <a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>,
<a href="http://www.sgi.com/tech/stl/EqualityComparable.html"><code>Equality
Comparable</code></a> and must interoperate with
<a href="../../../functional/hash/index.html">Boost.Hash</a>.
The first requirement is probably met without any extra effort by the user,
not so the other two, except for the most common basic types of C++
and the standard library. Equality and hashing of <code>T</code> are used
internally by <code>flyweight&lt;T&gt;</code> internal factory to maintain the
common repository of unique <code>T</code> values referred to by the flyweight
objects. Consult the Boost.Hash documentation
<a href="../../../../doc/html/hash/custom.html">section</a> on extending
that library for custom data types.
</p>
<p>
As we have seen, equality and hash requirements on <code>T</code> are
imposed by the particular type of <i>flyweight factory</i> internally used by
<code>flyweight&lt;T&gt;</code>. We will see later how the user can customize
this factory to use equality and hash predicates other than the default,
or even switch to an entirely different kind of factory which may impose
another requirements on <code>T</code>, as described in the section on
<a href="configuration.html">configuring Boost.Flyweight</a>.
</p>
<hr>
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.Flyweight tutorial" border="0"><br>
Boost.Flyweight tutorial
</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="key_value.html"><img src="../next.gif" alt="key-value flyweights" border="0"><br>
Key-value flyweights
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised December 2nd 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

View File

@@ -0,0 +1,647 @@
<!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 - Configuring Boost.Flyweight</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="key_value.html">
<link rel="up" href="index.html">
<link rel="next" href="extension.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Tutorial: Configuring Boost.Flyweight</h1>
<div class="prev_link"><a href="key_value.html"><img src="../prev.gif" alt="key-value flyweights" border="0"><br>
Key-value flyweights
</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="extension.html"><img src="../next.gif" alt="extending Boost.Flyweight" border="0"><br>
Extending Boost.Flyweight
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#intro">Configurable aspects of Boost.Flyweight</a>
<ul>
<li><a href="#free_order_template">Free-order template parameter interface</a></li>
<li><a href="#header_inclusion">Header inclusion</a></li>
</ul>
</li>
<li><a href="#tagging">Tagging</a></li>
<li><a href="#factories">Factory specification</a>
<ul>
<li><a href="#factory_types">Types involved in the configuration of factories</a></li>
<li><a href="#hashed_factory"><code>hashed_factory</code></a></li>
<li><a href="#set_factory"><code>set_factory</code></a></li>
<li><a href="#assoc_container_factory"><code>assoc_container_factory</code></a></li>
</ul>
</li>
<li><a href="#holders">Holder specification</a>
<ul>
<li><a href="#static_holder"><code>static_holder</code></a></li>
<li><a href="#intermodule_holder"><code>intermodule_holder</code></a></li>
</ul>
</li>
<li><a href="#locking">Locking policies</a>
<ul>
<li><a href="#simple_locking"><code>simple_locking</code></a></li>
<li><a href="#no_locking"><code>no_locking</code></a></li>
</ul>
</li>
<li><a href="#tracking">Tracking policies</a>
<ul>
<li><a href="#refcounted"><code>refcounted</code></a></li>
<li><a href="#no_tracking"><code>no_tracking</code></a></li>
</ul>
</li>
</ul>
<h2><a name="intro">Configurable aspects of Boost.Flyweight</a></h2>
<p>
Most of the time, <code>flyweight</code> default configuration is just good
enough and the user need not care about further tuning of her <code>flyweight</code>
instantiations; however, when the necessity for more control over Boost.Flyweight
behavior arises, comprehensive mechanisms are provided to select, configure and
even extend the following implementation aspects:
<ul>
<li><a href="#tagging">Type tagging</a>.</li>
<li><a href="#factories">Factory</a> used to store the shared values
<code>flyweight</code> objects refer to.
</li>
<li><a href="#holders">Mechanism of instantiation</a> of the flyweight factory.</li>
<li>Internal <a href="#locking">synchronization mechanism</a> for access to
the internal factory in multithreaded environments.</li>
<li><a href="#tracking">Tracking policy</a> controlling how a value stored in the
factory is handled when all the flyweight objects associated to it are
destroyed.
</li>
</ul>
</p>
<h3><a name="free_order_template">Free-order template parameter interface</a></h3>
<p>
The <code>flyweight</code> class template features a "smart" specification
interface by which the configuration aspects can be provided as optional template arguments
in whatever order the user pleases. For instance, a tagged <code>flyweight</code>
of <code>std::string</code>s with a <a href="#set_factory">set-based factory</a> and
<a href="#no_tracking">no tracking</a> can be specified like this:
</p>
<blockquote><pre>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span> <span class=identifier>tag</span><span class=special>&lt;</span><span class=identifier>label_t</span><span class=special>&gt;,</span> <span class=identifier>set_factory</span><span class=special>&lt;&gt;,</span> <span class=identifier>no_tracking</span> <span class=special>&gt;</span>
</pre></blockquote>
<p>
or like this:
</p>
<blockquote><pre>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span> <span class=identifier>no_tracking</span><span class=special>,</span> <span class=identifier>tag</span><span class=special>&lt;</span><span class=identifier>label_t</span><span class=special>&gt;,</span> <span class=identifier>set_factory</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
</pre></blockquote>
<p>
or in any other order; only <code>std::string</code> is required to occupy
the first place in the specification.
</p>
<h3><a name="header_inclusion">Header inclusion</a></h3>
<p>
The example code shown at the <a href="basics.html#intro">introductory section</a>
uses the
<a href="../reference/index.html#flyweight_synopsis"><code>"boost/flyweight.hpp"</code></a>
convenience header, which simply includes the headers for the class template
<code>flyweight</code> and its default configuration components:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span> <span class=comment>// class template flyweight</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>hashed_factory</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span> <span class=comment>// hashed flyweight factory</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>static_holder</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span> <span class=comment>// regular factory instantiation</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>simple_locking</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span> <span class=comment>// simple locking policy</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>refcounted</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span> <span class=comment>// refcounting tracking policy</span>
</pre></blockquote>
<p>
When using components other than these, their specific headers must be
explicitly included.
</p>
<h2><a name="tagging">Tagging</a></h2>
<p>
Consider the following two types:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=identifier>name_t</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=identifier>ip_address_t</span><span class=special>;</span>
</pre></blockquote>
<p>
Although technically both types are identical, this is so by virtue of
coincidence, as there is no sensible relation between names and IP addresses.
Internally, the fact that <code>name_t</code> and <code>ip_address_t</code>
are the same flyweight type causes values of both classes to be stored together
in the same flyweight factory, although their respective ranges
are not expected to overlap. <i>Tagging</i> can be used to turn these
into really different types:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>name_tag</span><span class=special>{};</span>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span><span class=identifier>tag</span><span class=special>&lt;</span><span class=identifier>name_tag</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>name_t</span><span class=special>;</span>
<span class=keyword>struct</span> <span class=identifier>ip_address_tag</span><span class=special>{};</span>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span><span class=identifier>tag</span><span class=special>&lt;</span><span class=identifier>ip_address_tag</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>ip_address_t</span><span class=special>;</span>
</pre></blockquote>
<p>
Now, <code>name_t</code> and <code>ip_address_t</code> are different
flyweight classes having separate factories each. Tags are a purely syntactic
device: any type can be used for tagging inside the <code>tag</code>
construct, though good style recommends using tag classes with
descriptive names which are local to the context where the flyweight type
is being defined.
</p>
<h2><a name="factories">Factory specification</a></h2>
<p>
<code>flyweight</code> uses a type of internal component called
<i>factory</i> whose purpose is to store and retrieve the different values
flyweight objects refer to at a given time. By default, a factory based on
a hashed container is used, so that <code>flyweight&lt;T&gt;</code> is
actually equivalent to
</p>
<blockquote><pre>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>hashed_factory</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
</pre></blockquote>
<p>
where <code>hashed_factory</code> is a so-called <i>factory specifier</i>.
Boost.Flyweight provides several predefined factory specifiers, which not
only let the user select the specific type of factory used, but also
accept their own template arguments to customize each factory.
</p>
<h3><a name="factory_types">Types involved in the configuration of factories</a></h3>
<p>
A given <code>flyweight</code> instantiation has associated
<code>flyweight::key_type</code>
and <code>flyweight::value_type</code> types (which are equal in the case
of regular flyweights or different if <a href="key_value.html">key-value
flyweights</a>
are used). Also, there is an internal <code>Entry</code> type which
corresponds to the type of the objects actually stored in the factory:
<code>Entry</code> contains the shared <code>value_type</code> objects
of <code>flyweight</code> as well a some internal bookkeeping information;
also, <code>Entry</code> is implicitly convertible to
<code>const key_type&amp;</code>, so that factories can rely on
<code>key_type</code> to look up <code>Entrie</code>s. Since
<code>Entry</code> is internal to the implementation of <code>flyweight</code>,
it cannot be directly referred to by the user in the configuration of
factories. Instead, the proxy
<a href="../../../mpl/doc/refmanual/placeholders.html"><i>placeholder</i></a>
type <code>boost::mpl::_1</code> can be used.
</p>
<h3><a name="hashed_factory"><code>hashed_factory</code></a></h3>
<blockquote>
<b>Header:</b> <a href="../reference/factories.html#hashed_factory_synopsis"><code>"boost/flyweight/hashed_factory.hpp"</code></a><br>
<b>Syntax:</b> <code>hashed_factory&lt;[Hash[,Pred[,Allocator]]]&gt;</code>
</blockquote>
<p>
This specifier, which Boost.Flyweight takes by default, controls the usage of a
factory internally based in a hash container. Values are determined to be
equivalent by means of the
<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html"><code>Binary
Predicate</code></a> <code>Pred</code>, and indexed into the factory container
using <code>Hash</code>, which is assumed to be a <i>hash function</i>,
i.e. a
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html"><code>Unary
Function</code></a> assigning to each value a hash identifier of
type <code>std::size_t</code>. The <code>Allocator</code> parameter is
used by the factory container for its memory allocation needs. The default
types for these parameters are such that the expression
</p>
<blockquote><pre>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>hashed_factory</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
</pre></blockquote>
<p>
is equivalent to
</p>
<blockquote><pre>
<span class=identifier>flyweight</span><span class=special>&lt;</span>
<span class=identifier>T</span><span class=special>,</span>
<span class=identifier>hashed_factory</span><span class=special>&lt;</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special>&lt;</span><span class=identifier>key_value</span><span class=special>&gt;,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special>&lt;</span><span class=identifier>key_value</span><span class=special>&gt;,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<p>
where <code>key_type</code> is the key type of the flyweight and
<code>boost::mpl::_1</code>, as explained above, stands for the
internal <code>Entry</code> type of the elements stored in the factory.
Suppose we would like to configure <code>hashed_factory</code> for
a <code>std::string</code> flyweight with
a special hash predicate <code>special_hash</code> and a custom allocator
<code>custom_allocator</code>; this would be specified as follows:
</p>
<blockquote><pre>
<span class=identifier>flyweight</span><span class=special>&lt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
<span class=identifier>hashed_factory</span><span class=special>&lt;</span>
<span class=identifier>special_hash</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special>&lt;</span><span class=identifier>key_value</span><span class=special>&gt;,</span>
<span class=identifier>custom_allocator</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<h3><a name="set_factory"><code>set_factory</code></a></h3>
<blockquote>
<b>Header:</b> <a href="../reference/factories.html#set_factory_synopsis"><code>"boost/flyweight/set_factory.hpp"</code></a><br>
<b>Syntax:</b> <code>set_factory&lt;[Compare[,Allocator]]&gt;</code>
</blockquote>
<p>
<code>set_factory</code> resorts to an <code>std::set</code>-like ordered
container for the implementation of the flyweight factory.
<code>Compare</code> must be a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html"><code>Strict
Weak Ordering</code></a> on the value type <code>flyweight</code> is
acting upon; as is customary with STL ordered containers, two values
are considered equivalent if none is less than the other according to <code>Pred</code>.
<code>Allocator</code> is an allocator type passed along to the factory
internal container for its memory-related tasks. When default parameters are
used, the expression
</p>
<blockquote><pre>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>set_factory</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
</pre></blockquote>
<p>
is equivalent to
</p>
<blockquote><pre>
<span class=identifier>flyweight</span><span class=special>&lt;</span>
<span class=identifier>T</span><span class=special>,</span>
<span class=identifier>set_factory</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>key_type</span><span class=special>&gt;,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<p>
Usual tradeoffs arising in the comparison of ordered and hashed containers
also apply when choosing between <code>set_factory</code> and
<code>hashed_factory</code>:
so, set-based lookup and insertion of values are generally slower than those based on hashing,
but the latter can be affected by pathological worst-case scenarios with very
poor performance.
</p>
<h3><a name="assoc_container_factory"><code>assoc_container_factory</code></a></h3>
<blockquote>
<b>Header:</b> <a href="../reference/factories.html#assoc_container_factory_synopsis"><code>"boost/flyweight/assoc_container_factory.hpp"</code></a><br>
<b>Syntax:</b> <code>assoc_container_factory&lt;ContainerSpecifier&gt;</code>
</blockquote>
<p>
This specifier can be seen as a generalization of
<code>hashed_factory</code> and <code>set_factory</code> where the user
supplies the exact type of container on which the factory is based.
The way in which the container is specified might seem at first a little
daunting to those unfamiliar with the
<a href="../../../mpl/doc/index.html">Boost MPL Library</a>:
<code>ContainerSpecifier</code> must be an
<a href="lambda_expressions.html"><code>MPL Lambda
Expression</code></a> such that, when invoked with the
types <code>Entry</code> and <code>key_type</code>
explained <a href="#factory_types">above</a>, it produces the type of
a container of <code>Entry</code> elements satisfying the following
requirements:
<ol>
<li>The container type must be a model of
<a href="http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html"><code>Unique
Associative Container</code></a> where equivalence of <code>Entry</code>s
is determined by the <code>key_type</code> values the entries are convertible
to .
</li>
<li>The container must be <i>stable</i>, i.e. its iterators must remain valid
after insert and erase operations. Note that this condition is not met by
many existing implementations of hashed containers that invalidate iterators
upon a rehashing operation.
</li>
</ol>
</p>
<p>
Let us see what a container specifier looks like with an example.
Suppose we have our own ordered container like the following:
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Elem</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>Elem</span><span class=special>&gt;,</span>
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span><span class=identifier>Elem</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>ultrafast_set</span>
<span class=special>{</span>
<span class=special>...</span>
<span class=special>};</span>
</pre></blockquote>
<p>
Then <code>ultrafast_set</code> can be plugged into
<code>assoc_container_factory</code> like this:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
<span class=identifier>assoc_container_factory</span><span class=special>&lt;</span>
<span class=comment>// MPL lambda expression follows</span>
<b><span class=identifier>ultrafast_set</span><span class=special>&lt;</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=special>&gt;</span></b>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
</pre></blockquote>
<p>
As has been explained, <code>mpl::_1</code> is a so-called MPL
placeholder standing as a "slot" to be replaced with
<code>Entry</code> by the internal machinery of Boost.Flyweight.
Note that we have not
relied on the default argument of <code>ultrafast_set</code> for
<code>Compare</code> and instead we have provided a fixed
instantiation for <code>std::string</code>: this is so because
requirements state that the type with which <code>ContainerSpecifier</code>
will be filled in internally is convertible to <code>const key_type&amp;</code>
(here <code>const std::string&amp;</code>), and it is based on
<code>key_type</code> that lookup and equivalence of entries
should be determined. On the other hand,
the default argument for the <code>Allocator</code> parameter works
just fine, as is more apparent if we write it down explicitly:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
<span class=identifier>assoc_container_factory</span><span class=special>&lt;</span>
<b><span class=identifier>ultrafast_set</span><span class=special>&lt;</span>
<span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span></b>
<span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
</pre></blockquote>
<h2><a name="holders">Holder specification</a></h2>
<p>
Each flyweight type, that is, each distinct instantiation of the class
template <code>flyweight</code>, is associated with exactly one factory
object. In most cases, how this factory object is created is of little
importance to the user of Boost.Flyweight, but there are special
circumstances where control of this aspect is necessary. An internal
component called <i>holder</i> is in charge of instantiating the
factory class and some other internal information; this component is
stipulated by means of a <i>holder specifier</i>, <code>static_holder</code>
being the default one.
</p>
<h3><a name="static_holder"><code>static_holder</code></a></h3>
<blockquote>
<b>Header:</b> <a href="../reference/holders.html#static_holder_synopsis"><code>"boost/flyweight/static_holder.hpp"</code></a><br>
<b>Syntax:</b> <code>static_holder</code>
</blockquote>
<p>
This the default holder specifier of Boost.Flyweight, and produces
holders where the unique factory lives as a local static variable of the
program.
</p>
<h3><a name="intermodule_holder"><code>intermodule_holder</code></a></h3>
<blockquote>
<b>Header:</b> <a href="../reference/holders.html#intermodule_holder_synopsis"><code>"boost/flyweight/intermodule_holder.hpp"</code></a><br>
<b>Syntax:</b> <code>intermodule_holder</code>
</blockquote>
<p>
In most C++ environments, static variables do not mix well with
dynamically loaded modules in the sense that instances of the same
static variable can be duplicated across different modules, even
though by definition the variable should be unique. In many
cases, this duplication goes unnoticed if the modules do not communicate
between each other using the affected types, but consider this
case where such communication does happen:
</p>
<blockquote><pre>
<span class=comment>// module 1</span>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
<span class=comment>// produce_string is exported so that it can be dynamically
// linked</span>
<span class=identifier>flyweight_string</span> <span class=identifier>produce_string</span><span class=special>()</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>flyweight_string</span><span class=special>(</span><span class=string>&quot;boost&quot;</span><span class=special>);</span>
<span class=special>}</span>
</pre></blockquote>
<blockquote><pre>
<span class=comment>// main program</span>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>main</span><span class=special>()</span>
<span class=special>{</span>
<span class=special>...</span> <span class=comment>// import module 1</span>
<span class=identifier>flyweight_string</span> <span class=identifier>str1</span><span class=special>=</span><span class=identifier>produce_string</span><span class=special>();</span>
<span class=identifier>flyweight_string</span> <span class=identifier>str2</span><span class=special>(</span><span class=string>&quot;boost&quot;</span><span class=special>);</span>
<span class=identifier>assert</span><span class=special>(</span><span class=identifier>str1</span><span class=special>==</span><span class=identifier>str2</span><span class=special>);</span>
<span class=special>}</span>
</pre></blockquote>
<p>
In many environments, this program results in an assertion
failure because the flyweight factory object used
by <code>flyweight_string</code> as seen within module 1 is
not the same factory object as seen within the main program: hence
the value representations internally pointed to by <code>str1</code>
and <code>str2</code> will differ and will be mistakenly
considered as not equal. Many other problems might arise
due to factory duplication, including undefined behavior.
</p>
<p>
<code>intermodule_holder</code> specifies a factory holder which
is capable of avoiding the duplication problem and ensuring that
all modules of a program are using the same factory instance.
To fix the example above, it suffices to redefine
<code>flyweight_string</code> in both modules as:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span><span class=identifier><b>intermodule_holder</b></span><span class=special>&gt;</span> <span class=identifier>flyweight_string</span><span class=special>;</span>
</pre></blockquote>
<p>
<code>intermodule_holder</code> is considerably more onerous than
<code>static_holder</code> in terms of compilation times and
introduces a non-negligible overhead at program start-up, so its use
should be reserved to the situations where it is really necessary.
</p>
<h2><a name="locking">Locking policies</a></h2>
<p>
The internal factory associated to each <code>flyweight</code>
type is a shared resource and as such access to it must be properly
synchronized in multithreaded environments. A <i>locking policy</i>
specifies the synchronization mechanisms to be used for this purpose.
</p>
<h3><a name="simple_locking"><code>simple_locking</code></a></h3>
<blockquote>
<b>Header:</b> <a href="../reference/locking.html#simple_locking_synopsis"><code>"boost/flyweight/simple_locking.hpp"</code></a><br>
<b>Syntax:</b> <code>simple_locking</code>
</blockquote>
<p>
This is the default locking policy. It specifies the simplest native
synchronization primitives provided by the operating system, whenever
available.
</p>
<h3><a name="no_locking"><code>no_locking</code></a></h3>
<blockquote>
<b>Header:</b> <a href="../reference/locking.html#no_locking_synopsis"><code>"boost/flyweight/no_locking.hpp"</code></a><br>
<b>Syntax:</b> <code>no_locking</code>
</blockquote>
<p>
No synchronization is enforced so that irrestricted internal access
to the implementation shared resources is allowed.
Selecting <code>no_locking</code> results in somewhat faster execution than
the default <code>simple_locking</code>, but it renders the type
thread-unsafe, which can have catastrophic consequences.
This policy should not be used except in single-threaded environments or
when there is an absolute guarantee that the particular <code>flyweight</code>
type will not be used in a concurrent scenario.
</p>
<h2><a name="tracking">Tracking policies</a></h2>
<p>
A <i>tracking policy</i> controls the lifetimes of the <code>flyweight</code>
objects and can act based on this information. For instance, a suitable
tracking mechanism can determine when a given value stored in the factory
can be safely erased because it is no longer referenced by any
<code>flyweight</code>; this is precisely what the default tracking policy,
<code>refcounted</code>, does.
</p>
<h3><a name="refcounted"><code>refcounted</code></a></h3>
<blockquote>
<b>Header:</b> <a href="../reference/tracking.html#refcounted_synopsis"><code>"boost/flyweight/refcounted.hpp"</code></a><br>
<b>Syntax:</b> <code>refcounted</code>
</blockquote>
<p>
This tracking policy determines that values stored in the factory be
equipped with reference counting mechanisms so that a factory entry is
erased when the last <code>flyweight</code> object associated to it
is destroyed.
</p>
<h3><a name="no_tracking"><code>no_tracking</code></a></h3>
<blockquote>
<b>Header:</b> <a href="../reference/tracking.html#no_tracking_synopsis"><code>"boost/flyweight/no_tracking.hpp"</code></a><br>
<b>Syntax:</b> <code>no_tracking</code>
</blockquote>
<p>
No flyweight tracking is done when this policy is selected, which implies
that the values stored in the factory remain in it until program termination.
As compared with <code>refcounted</code>, <code>no_tracking</code> presents
advantages and drawbacks. The benefits are:
<ul>
<li>Non-tracked flyweight objects are faster to pass around than refcounted ones.</li>
<li>There is some reduction in memory usage due to the
absence of reference counters.</li>
</ul>
whereas potential drawbacks of using <code>no_tracking</code> include:
<ul>
<li>The number of unused entries stored in the factory can keep growing
during the program lifetime, which can become a problem for certain
patterns of flyweight creation where the set of active values "drifts"
over time.</li>
<li>There can be a potential delay during program termination, since
it is then when all the factory entries get destroyed at once.</li>
</ul>
</p>
<hr>
<div class="prev_link"><a href="key_value.html"><img src="../prev.gif" alt="key-value flyweights" border="0"><br>
Key-value flyweights
</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="extension.html"><img src="../next.gif" alt="extending Boost.Flyweight" border="0"><br>
Extending Boost.Flyweight
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised November 8th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

562
doc/tutorial/extension.html Normal file
View File

@@ -0,0 +1,562 @@
<!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>&lt;</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>&gt;</span>
<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>&amp;</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>&amp;</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span>
<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&lt;std::string&gt;</code> or
<code>flyweight&lt;key_value&lt;std::string,texture&gt; &gt;</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&amp;</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>&lt;</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>&gt;</span>
<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>&lt;</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>store_type</span><span class=special>;</span>
<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>&amp;</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>&lt;</span><span class=identifier>handle_type</span><span class=special>,</span> <span class=keyword>bool</span><span class=special>&gt;</span> <span class=identifier>p</span><span class=special>=</span><span class=identifier>store</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>x</span><span class=special>);</span>
<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>&lt;&lt;</span><span class=string>&quot;new: &quot;</span><span class=special>&lt;&lt;(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&amp;)</span><span class=identifier>x</span><span class=special>&lt;&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span>
<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>&lt;&lt;</span><span class=string>&quot;hit: &quot;</span><span class=special>&lt;&lt;(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&amp;)</span><span class=identifier>x</span><span class=special>&lt;&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span>
<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>&lt;&lt;</span><span class=string>&quot;del: &quot;</span><span class=special>&lt;&lt;(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&amp;)*</span><span class=identifier>h</span><span class=special>&lt;&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span>
<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>&amp;</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>)</span>
<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&lt;Key&gt;</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&amp;</code>
(which is about the only property known about <code>Entry</code>) is
exploited in the specification of <code>std::less&lt;Key&gt;</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>&lt;</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>&gt;</span>
<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>&lt;</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>&gt;</span> <span class=identifier>type</span><span class=special>;</span>
<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>&lt;</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</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>&gt;</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>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<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>&lt;</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>&gt;</span>
<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>&lt;</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>&gt;</span> <span class=identifier>type</span><span class=special>;</span>
<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>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<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>&lt;&gt;</span> <span class=keyword>struct</span> <span class=identifier>is_factory</span><span class=special>&lt;</span><span class=identifier>custom_factory_specifier</span><span class=special>&gt;:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span>
<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>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</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>&lt;</span><span class=identifier>custom_factory_specifier</span><span class=special>&gt;</span>
<span class=special>&gt;</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>&lt;</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>&gt;</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>&amp;</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>&lt;</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>&gt;</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>&lt;</span><span class=identifier>C</span><span class=special>&gt;</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>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>&gt;</span> <span class=identifier>custom_factory_specifier</span><span class=special>;</span>
</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>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>holder_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<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>&lt;&gt;</span> <span class=keyword>struct</span> <span class=identifier>is_holder</span><span class=special>&lt;</span><span class=identifier>custom_holder_specifier</span><span class=special>&gt;:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span>
<span class=special>}}</span>
<span class=comment>// 3: use the holder&lt;&gt; wrapper when passing the specifier
// to flyweight</span>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</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>&lt;</span><span class=identifier>custom_holder_specifier</span><span class=special>&gt;</span>
<span class=special>&gt;</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>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>locking_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<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>&lt;&gt;</span> <span class=keyword>struct</span> <span class=identifier>is_locking</span><span class=special>&lt;</span><span class=identifier>custom_locking</span><span class=special>&gt;:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span>
<span class=special>}}</span>
<span class=comment>// 3: use the locking&lt;&gt; wrapper when passing the policy
// to flyweight</span>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</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>&lt;</span><span class=identifier>custom_locking</span><span class=special>&gt;</span>
<span class=special>&gt;</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&amp;</code>. The expression is expected
to return
a type implicitly convertible to both <code>const Value&amp;</code>
and <code>const Key&amp;</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&amp;</code> to obtain the entry type for the factory,
which must be convertible to both <code>const Value&amp;</code> and
<code>const fw_t::key_type&amp;</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>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>tracking_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<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>&lt;&gt;</span> <span class=keyword>struct</span> <span class=identifier>is_tracking</span><span class=special>&lt;</span><span class=identifier>custom_tracking</span><span class=special>&gt;:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span>
<span class=special>}}</span>
<span class=comment>// 3: use the tracking&lt;&gt; wrapper when passing the policy
// to flyweight</span>
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special>&lt;</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>&lt;</span><span class=identifier>custom_tracking</span><span class=special>&gt;</span>
<span class=special>&gt;</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>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

170
doc/tutorial/index.html Normal file
View File

@@ -0,0 +1,170 @@
<!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</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="../index.html">
<link rel="up" href="../index.html">
<link rel="next" href="basics.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Tutorial</h1>
<div class="prev_link"><a href="../index.html"><img src="../prev.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="basics.html"><img src="../next.gif" alt="basics" border="0"><br>
Basics
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#rationale">Rationale</a></li>
<li><a href="#namespace">Namespace</a></li>
<li><a href="#guide">Guide to the reader</a></li>
<li><a href="basics.html">Basics</a></li>
<li><a href="key_value.html">Key-value flyweights</a></li>
<li><a href="configuration.html">Configuring Boost.Flyweight</a></li>
<li><a href="extension.html">Extending Boost.Flyweight</a></li>
<li><a href="technical.html">Technical issues</a></li>
<li><a href="lambda_expressions.html">Annex: MPL Lambda expressions</a></li>
</ul>
<h2><a name="rationale">Rationale</a></h2>
<span style="float:left;margin-right:20px;margin-bottom:20px">
<p align="center">
<img src="flyweight_rep.png"
alt="representation of a flyweight scenario"
width="424" height="320"><br>
<b>Fig. 1: Representation of a flyweight scenario.</b>
</p>
</span>
<p>
Consider an application that has to manage large quantities of objects of
moderate size, potentially requiring more memory than reasonably available.
When these objects are <i>immutable</i>, i.e. they do not modify its internal
state except maybe for reattaching to a new set of state data, and some
additional conditions are met, a very convenient optimization technique known
as the <i>flyweight pattern</i> can be introduced.
</p>
<p>
Let us say there are <i>N</i> different objects living at a given time
inside the application, globally taking <i>M</i> different values. If <i>N</i>
is much greater than <i>M</i>, that is, there are many equivalent objects,
we can eliminate the implicit redundancy by replacing the original objects with
handle classes which refer to a common repository of shared value objects,
as depicted in the figure. The handle objects or flyweights, which act as
proxies for the actual values, typically occupy the size of a mere pointer.
The larger the value classes, and the greater the <i>N</i>/<i>M</i> ratio,
the more significant the memory savings achieved by this tecnhique. The
classical example of application of the flyweight idiom is that of a word
processor: each letter in the document carries a large wealth of
information, such as its Unicode identifier, font, size, typesetting effects,
etc., but given that the degree of letter repetition in a document is extremely
high, implementing those letters as flyweight classes allows us to easily
handle documents ranging in the hundreds of thousands of characters.
</p>
<p>
Most presentations of the design pattern found in the literature do make a
distinction between the flyweight <i>intrinsic information</i> (the constant
data factored out into the repository) and <i>extrinsic</i>, mutable
information, which is stored along with the flyweight objects or passed
externally. This separation analysis can have some merit from the point of
view of application design, but when it comes to implementation extrinsic
information has no impact on the overall flyweight scheme. So,
Boost.Flyweight assumes that the type onto which the library operates
entirely consists of intrinsic information: this allows for a particularly
appealing realization of the idiom in C++ in which
<code>flyweight&lt;T&gt;</code> is an opaque type convertible to
<code>const T&amp;</code>.
</p>
<p>
The central repository of shared value objects is known as the <i>flyweight
factory</i>. This component is able to locate and return a reference to an
object with a given value, or insert the value if no copy was previously
stored. Boost.Flyweight controls the interaction of flyweights with
their factory transparently to the programmer, so that a casual user of the
library need not even be concerned about the presence of such factory.
Boost.Flyweight uses by default a factory based on a hashed container which
is expected to be suitable for most situations. When this is not the case, it
is possible to customize the factory or even replace it with another one of
a different type, either provided by Boost.Flyweight or defined by the user.
Other aspects of the implementation are also customizable and extendable.
</p>
<h2 clear="all" style="clear: all;">
<a name="namespace">Namespace</a>
</h2>
<p>
All the public types of Boost.Flyweight reside in namespace <code>::boost::flyweights</code>.
Additionaly, the main class template <code>flyweight</code> is lifted to namespace
<code>::boost</code> by means of a <code>using</code> declaration. For brevity of
exposition, the fragments of code in the documentation are written as if the following
directives were in effect:
</p>
<blockquote><pre>
<span class=keyword>using</span> <span class=keyword>namespace</span> <span class=special>::</span><span class=identifier>boost</span><span class=special>;</span>
<span class=keyword>using</span> <span class=keyword>namespace</span> <span class=special>::</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>flyweights</span><span class=special>;</span>
</pre></blockquote>
<h2><a name="guide">Guide to the reader</a></h2>
<p>
Although Boost.Flyweight features an extensive customization
framework controlling many internal implementation aspects, the library is designed
in such a way that most users need not be concerned about or
even aware of the underlying complexity. Learning to use Boost.Flyweight
as an off-the-shelf component can be acomplished merely by reading
the <a href="basics.html">basics</a> section and skimming through the
part on <a href="key_value.html">key-value flyweights</a>, the section on flyweight type
<a href="configuration.html#tagging">tagging</a> and the discussion of some
<a href="technical.html">technical issues</a>. The
<a href="configuration.html">configuration</a> section teaches how to fine tune the
different internal components of the library. Only very advanced usage
scenarios will require implementing user-provided pluggable components:
this is covered on the <a href="extension.html">extension</a> section.
</p>
<hr>
<div class="prev_link"><a href="../index.html"><img src="../prev.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="basics.html"><img src="../next.gif" alt="basics" border="0"><br>
Basics
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised August 13th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

231
doc/tutorial/key_value.html Normal file
View File

@@ -0,0 +1,231 @@
<!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 - Key-value flyweights</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="basics.html">
<link rel="up" href="index.html">
<link rel="next" href="configuration.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Tutorial: Key-value flyweights</h1>
<div class="prev_link"><a href="basics.html"><img src="../prev.gif" alt="basics" border="0"><br>
Basics
</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="configuration.html"><img src="../next.gif" alt="configuring Boost.Flyweight" border="0"><br>
Configuring Boost.Flyweight
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#key_value">Key-value flyweights</a>
<ul>
<li><a href="#key_extractor">Key extractors</a></li>
<li><a href="#requirements">Type requirements</a></li>
</ul>
</li>
</ul>
<h2><a name="key_value">Key-value flyweights</a></h2>
<p>
Continuing with our online game example, suppose we have a huge class for
handling rendering textures:
</p>
<blockquote><pre>
<span class=keyword>class</span> <span class=identifier>texture</span>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=identifier>texture</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=identifier>filename</span><span class=special>){/*</span> <span class=identifier>loads</span> <span class=identifier>texture</span> <span class=identifier>file</span> <span class=special>*/}</span>
<span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=identifier>get_filename</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// rest of the interface</span>
<span class=special>};</span>
</pre></blockquote>
<p>
and we decide to use <code>flyweight&lt;texture&gt;</code> to ease the
manipulation of these objects. Now consider this seemingly innocent
expression:
</p>
<blockquote><pre>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>texture</span><span class=special>&gt;</span> <span class=identifier>fw</span><span class=special>(</span><span class=string>&quot;grass.texture&quot;</span><span class=special>);</span>
</pre></blockquote>
<p>
Note that in order to construct <code>fw</code> we are implicitly
constructing a full grass texture object. The expression is mostly
equivalent to
</p>
<blockquote><pre>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>texture</span><span class=special>&gt;</span> <span class=identifier>fw</span><span class=special>(</span><span class=identifier>texture</span><span class=special>(</span><span class=string>&quot;grass.texture&quot;</span><span class=special>));</span>
</pre></blockquote>
<p>
This is unnaceptably costly: we are constructing a massive temporary
object just to throw it away in most cases, since Boost.Flyweight most
likely already has an internal equivalent object to which <code>fw</code>
will be bound --value sharing is the key feature behind the flyweight
pattern after all. In this particular example, texture filenames act
as a <i>key</i> to the actual texture objects: two texture objects
constructed from the same filename are equivalent. So, we would like
for filenames to be used for texture lookup and somehow be sure that
the costly texture construction is only performed when no equivalent
value has been found.
</p>
<p>
<code>flyweight&lt;T&gt;</code> makes this distinction between key and value
blurry because it uses <code>T</code> both as the key type and
its associated value type. When this is inefficient, as in our texture
example, we can explicity specify both types using the
<a href="../reference/key_value.html#key_value_construct"><code>key_value</code></a>
construct:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>key_value</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=special>...</span>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>key_value</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span><span class=identifier>texture</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>fw</span><span class=special>(</span><span class=string>&quot;grass.texture&quot;</span><span class=special>);</span>
</pre></blockquote>
<p>
So called <i>key-value flyweights</i> have then the form
<code>flyweight&lt;key_value&lt;K,T&gt; &gt;</code>: the key type <code>K</code> is
used to do the internal lookup for the associated values of type <code>T</code>. Key-value
flyweights guarantee that <code>T</code> values are not constructed except when
no other equivalent value exists; such construction is done from the associated
<code>K</code> value.
</p>
<h3><a name="key_extractor">Key extractors</a></h3>
<p>
Besides the key-based semantics on construction time, key-value flyweights
behave much the same as regular flyweights, although some differences persist.
Consider the following code, which poses no problems with regular
flyweights:
</p>
<blockquote><pre>
<span class=keyword>const</span> <span class=identifier>texture</span><span class=special>&amp;</span> <span class=identifier>get_texture</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>object</span><span class=special>&amp;);</span>
<span class=special>...</span>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>key_value</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span><span class=identifier>texture</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>fw</span><span class=special>;</span>
<span class=special>...</span>
<span class=identifier>fw</span><span class=special>=</span><span class=identifier>get_texture</span><span class=special>(</span><span class=identifier>obj</span><span class=special>);</span>
</pre></blockquote>
<p>
The assignment cannot possibly work, because a key of type <code>std::string</code>
is needed to do the internal lookup whereas we are passing a full texture object.
Indeed, the code produces the a compilation error similar to this:
</p>
<blockquote><pre>
error: 'boost::mpl::assertion_failed' : cannot convert parameter 1 from
'boost::mpl::failed ************(__thiscall boost::flyweights::detail::
regular_key_value&lt;Key,Value&gt;::rep_type::no_key_from_value_failure::
<b>NO_KEY_FROM_VALUE_CONVERSION_PROVIDED</b>::* ***********)(std::string,texture)'
to 'boost::mpl::assert&lt;false&gt;::type'...
</pre></blockquote>
<p>
It turns out that we can make the assignment work if only we provide a means
to retrieve the key from the value. This is not always possible, but in
our particular example the texture class does store the filename used for
construction, as indicated by the <code>texture::get_filename</code>
member function. We take advantage of this by specifying a
suitable <a href="../reference/key_value.html#key_extractor"><i>key
extractor</i></a> as part of the flyweight type definition:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>texture_filename_extractor</span>
<span class=special>{</span>
<span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>texture</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>x</span><span class=special>.</span><span class=identifier>get_filename</span><span class=special>();</span>
<span class=special>}</span>
<span class=special>};</span>
<span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>key_value</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span><span class=identifier>texture</span><span class=special>,</span><span class=identifier>texture_filename_extractor</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>fw</span><span class=special>;</span>
<span class=special>...</span>
<span class=identifier>fw</span><span class=special>=</span><span class=identifier>get_texture</span><span class=special>(</span><span class=identifier>obj</span><span class=special>);</span> <span class=comment>// OK now</span>
</pre></blockquote>
<p>
The specification of a key extractor in the
definition of a key-value flyweight results in internal space optimizations,
as the keys need not be stored along the values but are retrieved from
them instead. So, it is always a good idea to provide a key extractor when
possible even if your program does not contain assignment statements like
the one above.
</p>
<p>
Examples <a href="../examples.html#example2">2</a> and
<a href="../examples.html#example5">5</a>
of the examples section make use of key-value flyweights.
</p>
<h3><a name="requirements">Type requirements</a></h3>
<p>
Many of the requirements imposed on <code>T</code> for
<a href="basics.html#requirements">regular flyweights</a> move to the key
type in the case of a key-value <code>flyweight&lt;key_value&lt;K,T&gt; &gt;</code>.
Now it is <code>K</code> that must be
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>,
<a href="http://www.sgi.com/tech/stl/EqualityComparable.html"><code>Equality
Comparable</code></a> and interoperate with
<a href="../../../functional/hash/index.html">Boost.Hash</a>, where equality and
hash compatibility are requirements imposed by the default internal factory of
Boost.Flyweight and can change if this factory is further configured or replaced
by the user. The only requisite retained on <code>T</code> is that it must be
constructible from <code>K</code>; only in the case that a flyweight is directly
assigned a <code>T</code> object is also <code>T</code> required to be
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>.
</p>
<hr>
<div class="prev_link"><a href="basics.html"><img src="../prev.gif" alt="basics" border="0"><br>
Basics
</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="configuration.html"><img src="../next.gif" alt="configuring Boost.Flyweight" border="0"><br>
Configuring Boost.Flyweight
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised December 2nd 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

View File

@@ -0,0 +1,181 @@
<!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 - Annex - MPL lambda expressions</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="technical.html">
<link rel="up" href="index.html">
<link rel="next" href="../reference/index.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Tutorial Annex: MPL lambda expressions</h1>
<div class="prev_link"><a href="technical.html"><img src="../prev.gif" alt="technical issues" border="0"><br>
Technical issues
</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="../reference/index.html"><img src="../next.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div><br clear="all" style="clear: all;">
<hr>
<p>This short introduction to lambda expressions is meant for readers unfamiliar
with the <a href="../../../mpl/doc/index.html">Boost MPL Library</a> who
want to rapidly acquire a working knowledge of the basic concepts for the purposes
of using them in Boost.Flyweight. Please refer to the Boost.MPL documentation
for further information beyond these introductory notes.
</p>
<p>
The specifiers defined by Boost.Flyweight rely heavily on the
<a href="../../../mpl/doc/refmanual/lambda-expression.html"><code>Lambda
Expression</code></a> concept defined by the
<a href="../../../mpl/doc/index.html">Boost MPL Library</a>. A lambda
expression can be thought of as a compile-time "type function", an entity (a
concrete type, actually) that can be invoked with a list of types and returns
some associated type in its turn. Consider for instance an arbitrary class
template:
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Q</span><span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>foo</span>
<span class=special>{</span>
<span class=special>...</span>
<span class=special>};</span>
</pre></blockquote>
<p>
and suppose we want to have a lambda expression that, when invoked
with some generic types <code>Arg1</code> and <code>Arg2</code>,
returns <code>foo&lt;Arg1,Arg2&gt;</code>. Such a lambda expression
can be implemented in two ways
<ol>
<li>As a
<a href="../../../mpl/doc/refmanual/metafunction-class.html"><code>MPL
Metafunction Class</code></a>, a type with a special nested class template
named <code>apply</code>:
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>foo_specifier</span>
<span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Arg1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg2</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>apply</span>
<span class=special>{</span>
<span class=comment>// this is the &quot;return type&quot; of foo_specifier</span>
<span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special>&lt;</span><span class=identifier>Arg1</span><span class=special>,</span><span class=identifier>Arg2</span><span class=special>&gt;</span> <span class=identifier>type</span><span class=special>;</span>
<span class=special>};</span>
<span class=special>};</span>
</pre></blockquote>
</li>
<li>
As a
<a href="../../../mpl/doc/refmanual/placeholder-expression.html"><code>MPL
Placeholder Expression</code></a>, a class template instantiated with one or
more <i>placeholders</i>:
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</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>&gt;</span> <span class=identifier>foo_specifier</span><span class=special>;</span>
</pre></blockquote>
Note that, in this case, <code>foo_specifier</code> is a concrete type, much
as <code>int</code> or <code>std::set&lt;std::string&gt;</code> are; yet,
MPL internal mechanisms are able to detect that this type has been gotten
from instantiating a class template with placeholders <code>boost::mpl::_1</code>
and <code>boost::mpl::_2</code> and take these placeholders as slots to
be substituted for actual types (the first and second type supplied,
respectively) when <code>foo_specifier</code> is
invoked. So, an instantiation of <code>foo</code> can be used
to refer back to the <code>foo</code> class template itself! The net
effect is the same as with metafunctions, but placeholder expressions spare
us the need to write boilerplate metafunction classes
--and the kind of metaprogramming magic they depend on has an undeniable
beauty to it.
</li>
</ol>
So far the examples shown just forward the arguments <code>Arg1</code> and
<code>Arg2</code> directly to a class template without further elaboration,
but there is nothing preventing us from doing some argument manipulation,
like, for instance, switching their places:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>foo_specifier</span>
<span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Arg1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg2</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>apply</span><span class=special>{</span><span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special>&lt;</span><span class=identifier>Arg2</span><span class=special>,</span><span class=identifier>Arg1</span><span class=special>&gt;</span> <span class=identifier>type</span><span class=special>;};</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_2</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>&gt;</span> <span class=identifier>foo_specifier</span><span class=special>;</span>
</pre></blockquote>
<p>
passing placeholder subexpressions as arguments to the overall expression:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>foo_specifier</span>
<span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Arg1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg2</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>apply</span><span class=special>{</span><span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>Arg1</span><span class=special>&gt;,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>Arg2</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>type</span><span class=special>;};</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special>&lt;</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>&gt;,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_2</span><span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>foo_specifier</span><span class=special>;</span>
</pre></blockquote>
<p>
or accepting less or more arguments than the class template itself
(the number of parameters of a lambda expression is called its <i>arity</i>):
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>foo_specifier</span>
<span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Arg1</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>apply</span><span class=special>{</span><span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special>&lt;</span><span class=identifier>Arg1</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>Arg1</span><span class=special>&gt;</span> <span class=identifier>type</span><span class=special>;};</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>foo_specifier</span><span class=special>;</span>
<span class=keyword>struct</span> <span class=identifier>foo_specifier</span>
<span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Arg1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg2</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Arg3</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>apply</span><span class=special>{</span><span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special>&lt;</span><span class=identifier>Arg1</span><span class=special>,</span><span class=identifier>foo</span><span class=special>&lt;</span><span class=identifier>Arg2</span><span class=special>,</span><span class=identifier>Arg3</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>type</span><span class=special>;};</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</span><span class=identifier>foo</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_2</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>_3</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>foo_specifier</span><span class=special>;</span>
</pre></blockquote>
<hr>
<div class="prev_link"><a href="technical.html"><img src="../prev.gif" alt="technical issues" border="0"><br>
Technical issues
</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="../reference/index.html"><img src="../next.gif" alt="Boost.Flyweight reference" border="0"><br>
Boost.Flyweight reference
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised August 13th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

193
doc/tutorial/technical.html Normal file
View File

@@ -0,0 +1,193 @@
<!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 - Technical issues</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="extension.html">
<link rel="up" href="index.html">
<link rel="next" href="lambda_expressions.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="Boost logo" align=
"middle" width="277" height="86">Boost.Flyweight Tutorial: Technical issues</h1>
<div class="prev_link"><a href="extension.html"><img src="../prev.gif" alt="extending Boost.Flyweight" border="0"><br>
Extending 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="lambda_expressions.html"><img src="../next.gif" alt="annex: MPL lambda expressions" border="0"><br>
Annex: MPL lambda expressions
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#static_init">Static data initialization</a></li>
</ul>
<h2><a name="static_init">Static data initialization</a></h2>
<p>
For any given <code>T</code>, the type <code>flyweight&lt;T&gt;</code>
maintains some class-wide or static data that needs to be properly
initialized before the class can be used. The internal machinery of
Boost.Flyweight guarantees that static data initialization
takes place automatically before the first use of the particular
<code>flyweight&lt;T&gt;</code> instantiation in the program, and in
any case always during the so-called <i>dynamic initialization phase</i>
of the program startup sequence. Although this is not strictly
required by the C++ standard, in current practice dynamic initialization
is completed before <code>main()</code> begins.
</p>
<p>
So, for all practical purposes, static data initialization is performed
before <code>main()</code> or before the first pre-<code>main()</code>
usage of the class, for instance if we declare a global
<code>static flyweight&lt;T&gt;</code> object. This covers the vast
majority of usage cases in a transparent manner, but there are
some scenarios where the automatic static data initialization
policy of Boost.Flyweight can fail:
</p>
<blockquote><pre>
<span class=comment>// global thread pool</span>
<span class=keyword>class</span> <span class=identifier>thread_pool</span>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=identifier>thread_pool</span><span class=special>()</span>
<span class=special>{</span>
<span class=keyword>for</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>i</span><span class=special>=</span><span class=number>0</span><span class=special>;</span><span class=identifier>i</span><span class=special>&lt;</span><span class=number>100</span><span class=special>;++</span><span class=identifier>i</span><span class=special>)</span><span class=identifier>p</span><span class=special>[</span><span class=identifier>i</span><span class=special>]=</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>thread</span><span class=special>&gt;(</span><span class=keyword>new</span> <span class=identifier>thread</span><span class=special>(</span><span class=identifier>thread_fun</span><span class=special>));</span>
<span class=special>}</span>
<span class=keyword>private</span><span class=special>:</span>
<span class=keyword>static</span> <span class=keyword>void</span> <span class=identifier>thread_fun</span><span class=special>()</span>
<span class=special>{</span>
<span class=comment>// uses flyweight&lt;std::string&gt;</span>
<span class=special>}</span>
<span class=identifier>array</span><span class=special>&lt;</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>thread</span><span class=special>&gt;,</span><span class=number>100</span><span class=special>&gt;</span> <span class=identifier>p</span><span class=special>;</span>
<span class=special>};</span>
<span class=keyword>static</span> <span class=identifier>thread_pool</span> <span class=identifier>thpool</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>main</span><span class=special>()</span>
<span class=special>{</span>
<span class=special>...</span>
</pre></blockquote>
<p>
The global pool of the example launches several threads, each of which
internally uses <code>flyweight&lt;std::string&gt;</code>.
Static data initialization can potentially be executed twice concurrently
if two threads happen to collide on the first usage of
<code>flyweight&lt;std::string&gt;</code>: Boost.Flyweight initialization
does not consider thread safety. So, we need to explicitly take care of
static data initialization in a thread safe context before launching
the threads:
</p>
<blockquote><pre>
<span class=keyword>class</span> <span class=identifier>thread_pool</span>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=identifier>thread_pool</span><span class=special>()</span>
<span class=special>{</span>
<b><span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;::</span><span class=identifier>init</span><span class=special>();</span></b>
<span class=keyword>for</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>i</span><span class=special>=</span><span class=number>0</span><span class=special>;</span><span class=identifier>i</span><span class=special>&lt;</span><span class=number>100</span><span class=special>;++</span><span class=identifier>i</span><span class=special>)</span><span class=identifier>p</span><span class=special>[</span><span class=identifier>i</span><span class=special>]=</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>thread</span><span class=special>&gt;(</span><span class=keyword>new</span> <span class=identifier>thread</span><span class=special>(</span><span class=identifier>thread_fun</span><span class=special>));</span>
<span class=special>}</span>
<span class=special>...</span>
</pre></blockquote>
<p>
The static member function <code>init</code> is not thread safe, either: in our particular
example it just happens to be called in a single threaded environment.
When concurrency can happen, <code>flyweight&lt;T&gt;::init</code> must
be properly synchronized by the programmer by using some mutual exclusion
mechanisms of her own.
</p>
<p>
The following is another example where the default static initialization
provided by Boost.Flyweight can fail:
</p>
<blockquote><pre>
<span class=keyword>static</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>v</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>main</span><span class=special>()</span>
<span class=special>{</span>
<span class=comment>// use v</span>
<span class=special>}</span>
</pre></blockquote>
<p>
In some environments, the program above fails at termination time with something
like the following:
</p>
<blockquote><pre>
Assertion failed: count()==0, file c:\boost\flyweight\refcounted.hpp, line 55
</pre></blockquote>
<p>
What is the problem? Although the type of <code>v</code> involves
<code>flyweight&lt;std::string&gt;</code>, constructing <code>v</code> as an empty vector
need not create any flyweight object proper; so,
it is perfectly possible that the static initialization of
<code>flyweight&lt;std::string&gt;</code> happens <i>after</i> the construction
of <code>v</code>; when this is the case, the static destruction of
the associated factory will occur <i>before</i> <code>v</code>'s
destruction, leaving the vector with dangling flyweights.
Again, the solution consists in explicitly forcing the static instantiation
of <code>flyweight&lt;std::string&gt;</code> before <code>v</code> is
created. Here, calling
the function <code>flyweight&lt;std::string&gt;::init</code> is a little
cumbersome, so we can resort to the utility type
<code>flyweight&lt;std::string&gt;::initializer</code> to do that job for us:
</p>
<blockquote><pre>
<span class=comment>// equivalent to calling flyweight&lt;std::string&gt;::init()</span>
<b><span class=keyword>static</span> <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;::</span><span class=identifier>initializer</span> <span class=identifier>fwinit</span><span class=special>;</span></b>
<span class=keyword>static</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>v</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>main</span><span class=special>()</span>
<span class=special>{</span>
<span class=comment>// use v; no dangling flyweights at termination now</span>
<span class=special>}</span>
</pre></blockquote>
<hr>
<div class="prev_link"><a href="extension.html"><img src="../prev.gif" alt="extending Boost.Flyweight" border="0"><br>
Extending 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="lambda_expressions.html"><img src="../next.gif" alt="annex: MPL lambda expressions" border="0"><br>
Annex: MPL lambda expressions
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised August 11th 2008</p>
<p>&copy; Copyright 2006-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;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>

BIN
doc/up.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

49
example/Jamfile.v2 Normal file
View File

@@ -0,0 +1,49 @@
# Boost.Flyweight examples Jamfile
#
# Copyright 2006-2008 Joaquín M López Muñoz.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# See http://www.boost.org/libs/flyweight for library home page.
project
: requirements
<os>LINUX:<threading>multi
;
exe basic
: basic.cpp
: <include>$(BOOST_ROOT)
;
exe composite
: composite.cpp
: <include>$(BOOST_ROOT)
;
exe custom_factory
: custom_factory.cpp
: <include>$(BOOST_ROOT)
;
exe fibonacci
: fibonacci.cpp
: <include>$(BOOST_ROOT)
;
exe html
: html.cpp
: <include>$(BOOST_ROOT)
;
exe key_value
: key_value.cpp
: <include>$(BOOST_ROOT)
;
exe perf
: perf.cpp
: <include>$(BOOST_ROOT)
: release
;

152
example/basic.cpp Normal file
View File

@@ -0,0 +1,152 @@
/* Boost.Flyweight basic example.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/bind.hpp>
#include <boost/flyweight.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
using namespace boost::flyweights;
/* Information associated to a given user of some massive system.
* first_name and last_name are turned into flyweights to leverage the
* implicit redundancy of names within the user community.
*/
struct user_entry
{
flyweight<std::string> first_name;
flyweight<std::string> last_name;
int age;
user_entry();
user_entry(const char* first_name,const char* last_name,int age);
user_entry(const user_entry& x);
};
/* flyweight<std::string> default ctor simply calls the default ctor of
* std::string.
*/
user_entry::user_entry()
{}
/* flyweight<std::string> is constructible from a const char* much as
* a std::string is.
*/
user_entry::user_entry(const char* f,const char* l,int a):
first_name(f),
last_name(l),
age(a)
{}
/* flyweight's are copyable and assignable --unlike std::string,
* copy and assignment of flyweight<std::string>s do not ever throw.
*/
user_entry::user_entry(const user_entry& x):
first_name(x.first_name),
last_name(x.last_name),
age(x.age)
{}
/* flyweight<std::string> has operator==,!=,<,>,<=,>= with the same
* semantics as those of std::string.
*/
bool same_name(const user_entry& user1,const user_entry& user2)
{
bool b=user1.first_name==user2.first_name &&
user1.last_name==user2.last_name;
return b;
}
/* operator<< forwards to the std::string overload */
std::ostream& operator<<(std::ostream& os,const user_entry& user)
{
return os<<user.first_name<<" "<<user.last_name<<" "<<user.age;
}
/* operator>> internally uses std::string's operator>> */
std::istream& operator>>(std::istream& is,user_entry& user)
{
return is>>user.first_name>>user.last_name>>user.age;
}
std::string full_name(const user_entry& user)
{
std::string full;
/* get() returns the underlying const std::string& */
full.reserve(
user.first_name.get().size()+user.last_name.get().size()+1);
/* here, on the other hand, implicit conversion is used */
full+=user.first_name;
full+=" ";
full+=user.last_name;
return full;
}
/* flyweight<std::string> value is immutable, but a flyweight object can
* be assigned a different value.
*/
void change_name(user_entry& user,const std::string& f,const std::string& l)
{
user.first_name=f;
user.last_name=l;
}
int main()
{
/* play a little with a vector of user_entry's */
std::string users_txt=
"olegh smith 31\n"
"john brown 28\n"
"anna jones 45\n"
"maria garcia 30\n"
"john fox 56\n"
"anna brown 19\n"
"thomas smith 46\n"
"andrew martin 28";
std::vector<user_entry> users;
std::istringstream iss(users_txt);
while(iss){
user_entry u;
if(iss>>u)users.push_back(u);
}
change_name(users[0],"oleg","smith");
user_entry anna("anna","jones",20);
std::replace_if(
users.begin(),users.end(),
boost::bind(same_name,_1,anna),
anna);
std::copy(
users.begin(),users.end(),
std::ostream_iterator<user_entry>(std::cout,"\n"));
return 0;
}

179
example/composite.cpp Normal file
View File

@@ -0,0 +1,179 @@
/* Boost.Flyweight example of a composite design.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/flyweight.hpp>
#include <boost/functional/hash.hpp>
#include <boost/tokenizer.hpp>
#include <boost/variant.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/recursive_wrapper.hpp>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
using namespace boost::flyweights;
/* A node of a lisp-like list can be modeled as a boost::variant of
* 1. A string (primitive node)
* 2. A vector of nodes (embedded list)
* To save space, 2 is stored as a vector of flyweights.
* As is usual with recursive data structures, a node can be thought
* of also as a list. To close the flyweight circle, the final
* type list is a flyweight wrapper, so that the final structure can
* be described as follows in BNF-like style:
*
* list ::= flyweight<list_impl>
* list_impl ::= std::string | std::vector<list>
*/
struct list_elems;
typedef boost::variant<
std::string,
boost::recursive_wrapper<list_elems>
> list_impl;
struct list_elems:std::vector<flyweight<list_impl> >{};
typedef flyweight<list_impl> list;
/* list_impl must be hashable to be used by flyweight: If a
* node is a std::string, its hash resolves to that of the string;
* if it is a vector of nodes, we compute the hash by combining
* the *addresses* of the stored flyweights' associated values: this is
* consistent because flyweight equality implies equality of reference.
* Using this trick instead of hashing the node values themselves
* allow us to do the computation without recursively descending down
* through the entire data structure.
*/
struct list_hasher:boost::static_visitor<std::size_t>
{
std::size_t operator()(const std::string& str)const
{
boost::hash<std::string> h;
return h(str);
}
std::size_t operator()(
const boost::recursive_wrapper<list_elems>& elmsw)const
{
const list_elems& elms=elmsw.get();
std::size_t res=0;
for(list_elems::const_iterator it=elms.begin(),it_end=elms.end();
it!=it_end;++it){
const list_impl* p=&it->get();
boost::hash_combine(res,p);
}
return res;
}
};
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace boost{
#endif
std::size_t hash_value(const list_impl& limpl)
{
return boost::apply_visitor(list_hasher(),limpl);
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
} /* namespace boost */
#endif
/* basic pretty printer with indentation according to the nesting level */
struct list_pretty_printer:boost::static_visitor<>
{
list_pretty_printer():nest(0){}
void operator()(const std::string& str)
{
indent();
std::cout<<str<<"\n";
}
void operator()(const boost::recursive_wrapper<list_elems>& elmsw)
{
indent();
std::cout<<"(\n";
++nest;
const list_elems& elms=elmsw.get();
for(list_elems::const_iterator it=elms.begin(),it_end=elms.end();
it!=it_end;++it){
boost::apply_visitor(*this,it->get());
}
--nest;
indent();
std::cout<<")\n";
}
private:
void indent()const
{
for(int i=nest;i--;)std::cout<<" ";
}
int nest;
};
void pretty_print(const list& l)
{
list_pretty_printer pp;
boost::apply_visitor(pp,l.get());
}
/* list parser */
template<typename InputIterator>
list parse_list(InputIterator& first,InputIterator last,int nest)
{
list_elems elms;
while(first!=last){
std::string str=*first++;
if(str=="("){
elms.push_back(parse_list(first,last,nest+1));
}
else if(str==")"){
if(nest==0)throw std::runtime_error("unmatched )");
return list(elms);
}
else{
elms.push_back(list(str));
}
}
if(nest!=0)throw std::runtime_error("unmatched (");
return list(elms);
}
list parse_list(const std::string str)
{
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
tokenizer tok(str,boost::char_separator<char>(" ","()"));
tokenizer::iterator begin=tok.begin();
return parse_list(begin,tok.end(),0);
}
int main()
{
std::cout<<"enter list: ";
std::string str;
std::getline(std::cin,str);
try{
pretty_print(parse_list(str));
}
catch(const std::exception& e){
std::cout<<"error: "<<e.what()<<"\n";
}
return 0;
}

122
example/custom_factory.cpp Normal file
View File

@@ -0,0 +1,122 @@
/* Boost.Flyweight example of custom factory.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
/* We include the default components of Boost.Flyweight except the factory,
* which will be provided by ourselves.
*/
#include <boost/flyweight/flyweight.hpp>
#include <boost/flyweight/factory_tag.hpp>
#include <boost/flyweight/static_holder.hpp>
#include <boost/flyweight/simple_locking.hpp>
#include <boost/flyweight/refcounted.hpp>
#include <boost/tokenizer.hpp>
#include <functional>
#include <iostream>
#include <set>
using namespace boost::flyweights;
/* custom factory based on std::set with some logging capabilities */
/* Entry is the type of the stored objects. Value is the type
* on which flyweight operates, that is, the T in flyweoght<T>. It
* is guaranteed that Entry implicitly converts to const Value&.
* The factory class could accept other template arguments (for
* instance, a comparison predicate for the values), we leave it like
* that for simplicity.
*/
template<typename Entry,typename Key>
class verbose_factory_class
{
/* Entry store. Since Entry is implicitly convertible to const Key&,
* we can directly use std::less<Key> as the comparer for std::set.
*/
typedef std::set<Entry,std::less<Key> > store_type;
store_type store;
public:
typedef typename store_type::iterator handle_type;
handle_type insert(const Entry& x)
{
/* locate equivalent entry or insert otherwise */
std::pair<handle_type, bool> p=store.insert(x);
if(p.second){ /* new entry */
std::cout<<"new: "<<(const Key&)x<<std::endl;
}
else{ /* existing entry */
std::cout<<"hit: "<<(const Key&)x<<std::endl;
}
return p.first;
}
void erase(handle_type h)
{
std::cout<<"del: "<<(const Key&)*h<<std::endl;
store.erase(h);
}
const Entry& entry(handle_type h)
{
return *h; /* handle_type is an iterator */
}
};
/* Specifier for verbose_factory_class. The simplest way to tag
* this struct as a factory specifier, so that flyweight<> accepts it
* as such, is by deriving from boost::flyweights::factory_marker.
* See the documentation for info on alternative tagging methods.
*/
struct verbose_factory: factory_marker
{
template<typename Entry,typename Key>
struct apply
{
typedef verbose_factory_class<Entry,Key> type;
} ;
};
/* ready to use it */
typedef flyweight<std::string,verbose_factory> fw_string;
int main()
{
typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
std::string text=
"I celebrate myself, and sing myself, "
"And what I assume you shall assume, "
"For every atom belonging to me as good belongs to you. "
"I loafe and invite my soul, "
"I lean and loafe at my ease observing a spear of summer grass. "
"My tongue, every atom of my blood, form'd from this soil, this air, "
"Born here of parents born here from parents the same, and their "
" parents the same, "
"I, now thirty-seven years old in perfect health begin, "
"Hoping to cease not till death.";
std::vector<fw_string> v;
text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
for(text_tokenizer::iterator it=tok.begin();it!=tok.end();){
v.push_back(fw_string(*it++));
}
return 0;
}

58
example/fibonacci.cpp Normal file
View File

@@ -0,0 +1,58 @@
/* Boost.Flyweight example of flyweight-based memoization.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/flyweight.hpp>
#include <boost/flyweight/key_value.hpp>
#include <boost/flyweight/no_tracking.hpp>
#include <boost/noncopyable.hpp>
#include <iostream>
using namespace boost::flyweights;
/* Memoized calculation of Fibonacci numbers */
/* This class takes an int n and calculates F(n) at construction time */
struct compute_fibonacci;
/* A Fibonacci number can be modeled as a key-value flyweight
* We choose the no_tracking policy so that the calculations
* persist for future use throughout the program. See
* Tutorial: Configuring Boost.Flyweight: Tracking policies for
* further information on tracking policies.
*/
typedef flyweight<key_value<int,compute_fibonacci>,no_tracking> fibonacci;
/* Implementation of compute_fibonacci. Note that the construction
* of compute_fibonacci(n) uses fibonacci(n-1) and fibonacci(n-2),
* which effectively memoizes the computation.
*/
struct compute_fibonacci:private boost::noncopyable
{
compute_fibonacci(int n):
result(n==0?0:n==1?1:fibonacci(n-2).get()+fibonacci(n-1).get())
{}
operator int()const{return result;}
int result;
};
int main()
{
/* list some Fibonacci numbers */
for(int n=0;n<40;++n){
std::cout<<"F("<<n<<")="<<fibonacci(n)<<std::endl;
}
return 0;
}

343
example/html.cpp Normal file
View File

@@ -0,0 +1,343 @@
/* Boost.Flyweight example of flyweight-based formatted text processing.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/flyweight.hpp>
#include <boost/functional/hash.hpp>
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{using ::exit;using ::tolower;}
#endif
using namespace boost::flyweights;
/* See the portability section of Boost.Hash at
* http://boost.org/doc/html/hash/portability.html
* for an explanation of the ADL-related workarounds.
*/
namespace boost{
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace flyweights{
#endif
/* We hash the various flyweight types used in the program hashing
* a *pointer* to their contents: this is consistent as equality of
* flyweights implies equality of references.
*/
template<typename T>
std::size_t hash_value(const flyweight<T>& x)
{
boost::hash<const T*> h;
return h(&x.get());
}
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
} /* namespace flyweights */
#endif
} /* namespace boost */
/* An HTML tag consists of a name and optional properties of the form
* name1=value1 ... namen=valuen. We do not need to parse the properties
* for the purposes of the program, hence they are all stored in
* html_tag_data::properties in raw form.
*/
struct html_tag_data
{
std::string name;
std::string properties;
};
bool operator==(const html_tag_data& x,const html_tag_data& y)
{
return x.name==y.name&&x.properties==y.properties;
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace boost{
#endif
std::size_t hash_value(const html_tag_data& x)
{
std::size_t res=0;
boost::hash_combine(res,x.name);
boost::hash_combine(res,x.properties);
return res;
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
} /* namespace boost */
#endif
typedef flyweight<html_tag_data> html_tag;
/* parse_tag is passed an iterator positioned at the first char of
* the tag after the opening '<' and returns, if succesful, a parsed tag
* and whether it is opening (<xx>) or closing (</xx>).
*/
enum tag_type{opening,closing,failure};
struct parse_tag_res
{
parse_tag_res(tag_type type_,const html_tag_data& tag_=html_tag_data()):
type(type_),tag(tag_){}
parse_tag_res(const parse_tag_res& x):type(x.type),tag(x.tag){}
tag_type type;
html_tag tag;
};
template<typename ForwardIterator>
parse_tag_res parse_tag(ForwardIterator& first,ForwardIterator last)
{
html_tag_data tag;
std::string buf;
bool in_quote=false;
for(ForwardIterator it=first;it!=last;){
char ch=*it++;
if(ch=='>'&&!in_quote){ /* ignore '>'s if inside quotes */
tag_type type;
std::string::size_type
bname=buf.find_first_not_of("\t\n\r "),
ename=bname==std::string::npos?
std::string::npos:
buf.find_first_of("\t\n\r ",bname),
bprop=ename==std::string::npos?
std::string::npos:
buf.find_first_not_of("\t\n\r ",ename);
if(bname==ename){ /* null name */
return parse_tag_res(failure);
}
else if(buf[bname]=='/'){ /* closing tag */
type=closing;
++bname;
}
else type=opening;
tag.name=buf.substr(bname,ename-bname);
std::transform( /* normalize tag name to lower case */
tag.name.begin(),tag.name.end(),tag.name.begin(),
(int(*)(int))std::tolower);
if(bprop!=std::string::npos){
tag.properties=buf.substr(bprop,buf.size());
}
first=it; /* result good, consume the chars */
return parse_tag_res(type,tag);
}
else{
if(ch=='"')in_quote=!in_quote;
buf+=ch;
}
}
return parse_tag_res(failure); /* end reached and found no '>' */
}
/* A character context is just a vector containing the tags enclosing the
* character, from the outermost level to the innermost.
*/
typedef std::vector<html_tag> html_context_data;
typedef flyweight<html_context_data> html_context;
/* A character is a char code plus its context.
*/
struct character_data
{
character_data(char code_=0,html_context context_=html_context()):
code(code_),context(context_){}
character_data(const character_data& x):code(x.code),context(x.context){}
char code;
html_context context;
};
bool operator==(const character_data& x,const character_data& y)
{
return x.code==y.code&&x.context==y.context;
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace boost{
#endif
std::size_t hash_value(const character_data& x)
{
std::size_t res=0;
boost::hash_combine(res,x.code);
boost::hash_combine(res,x.context);
return res;
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
} /* namespace boost */
#endif
typedef flyweight<character_data> character;
/* scan_html converts HTML code into a stream of contextualized characters.
*/
template<typename ForwardIterator,typename OutputIterator>
void scan_html(ForwardIterator first,ForwardIterator last,OutputIterator out)
{
html_context_data context;
while(first!=last){
if(*first=='<'){ /* tag found */
++first;
parse_tag_res res=parse_tag(first,last);
if(res.type==opening){ /* add to contex */
context.push_back(res.tag);
continue;
}
else if(res.type==closing){ /* remove from context */
/* Pop all tags from the innermost to the matching one; this takes
* care of missing </xx>s like vg. in <ul><li>hello</ul>.
*/
for(html_context_data::reverse_iterator rit=context.rbegin();
rit!=context.rend();++rit){
if(rit->get().name==res.tag.get().name){
context.erase(rit.base()-1,context.end());
break;
}
}
continue;
}
}
*out++=character(*first++,html_context(context));
}
}
/* HTML-producing utilities */
void print_opening_tag(std::ostream& os,const html_tag_data& x)
{
os<<"<"<<x.name;
if(!x.properties.empty())os<<" "<<x.properties;
os<<">";
}
void print_closing_tag(std::ostream& os,const html_tag_data& x)
{
/* SGML declarations (beginning with '!') are not closed */
if(x.name[0]!='!')os<<"</"<<x.name<<">";
}
/* change_context takes contexts from and to with tags
*
* from<- c1 ... cn fn+1 ... fm
* to <- c1 ... cn tn+1 ... tk
*
* (that is, they share the first n tags, n might be 0), and
* produces code closing fm ... fn+1 and opening tn+1 ... tk.
*/
template<typename OutputIterator>
void change_context(
const html_context_data& from,const html_context_data& to,
OutputIterator out)
{
std::ostringstream oss;
html_context_data::const_iterator
it0=from.begin(),
it0_end=from.end(),
it1=to.begin(),
it1_end=to.end();
for(;it0!=it0_end&&it1!=it1_end&&*it0==*it1;++it0,++it1);
while(it0_end!=it0)print_closing_tag(oss,*--it0_end);
while(it1!=it1_end)print_opening_tag(oss,*it1++);
std::string str=oss.str();
std::copy(str.begin(),str.end(),out);
}
/* produce_html is passed a bunch of contextualized characters and emits
* the corresponding HTML. The algorithm is simple: tags are opened and closed
* as a result of the context from one character to the following changing.
*/
template<typename ForwardIterator,typename OutputIterator>
void produce_html(ForwardIterator first,ForwardIterator last,OutputIterator out)
{
html_context context;
while(first!=last){
if(first->get().context!=context){
change_context(context,first->get().context,out);
context=first->get().context;
}
*out++=(first++)->get().code;
}
change_context(context,html_context(),out); /* close remaining context */
}
/* Without these explicit instantiations, MSVC++ 6.5/7.0 does not
* find some friend operators in certain contexts.
*/
character dummy1;
html_tag dummy2;
int main()
{
std::cout<<"input html file: ";
std::string in;
std::getline(std::cin,in);
std::ifstream ifs(in.c_str());
if(!ifs){
std::cout<<"can't open "<<in<<std::endl;
std::exit(EXIT_FAILURE);
}
typedef std::istreambuf_iterator<char> istrbuf_iterator;
std::vector<char> html_source;
std::copy(
istrbuf_iterator(ifs),istrbuf_iterator(),
std::back_inserter(html_source));
/* parse the HTML */
std::vector<character> scanned_html;
scan_html(
html_source.begin(),html_source.end(),std::back_inserter(scanned_html));
/* Now that we have the text as a vector of contextualized characters,
* we can shuffle it around and manipulate in almost any way we please.
* For instance, the following reverses the central portion of the doc.
*/
std::reverse(
scanned_html.begin()+scanned_html.size()/4,
scanned_html.begin()+3*(scanned_html.size()/4));
/* emit the resulting HTML */
std::cout<<"output html file: ";
std::string out;
std::getline(std::cin,out);
std::ofstream ofs(out.c_str());
if(!ofs){
std::cout<<"can't open "<<out<<std::endl;
std::exit(EXIT_FAILURE);
}
typedef std::ostreambuf_iterator<char> ostrbuf_iterator;
produce_html(scanned_html.begin(),scanned_html.end(),ostrbuf_iterator(ofs));
return 0;
}

99
example/key_value.cpp Normal file
View File

@@ -0,0 +1,99 @@
/* Boost.Flyweight example of use of key-value flyweights.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/array.hpp>
#include <boost/flyweight.hpp>
#include <boost/flyweight/key_value.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
using namespace boost::flyweights;
/* A class simulating a texture resource loaded from file */
class texture
{
public:
texture(const std::string& filename):filename(filename)
{
std::cout<<"loaded "<<filename<<" file"<<std::endl;
}
texture(const texture& x):filename(x.filename)
{
std::cout<<"texture["<<filename<<"] copied"<<std::endl;
}
~texture()
{
std::cout<<"unloaded "<<filename<<std::endl;
}
const std::string& get_filename()const{return filename;}
// rest of the interface
private:
std::string filename;
};
/* key extractor of filename strings from textures */
struct texture_filename_extractor
{
const std::string& operator()(const texture& x)const
{
return x.get_filename();
}
};
/* texture flyweight */
typedef flyweight<
key_value<std::string,texture,texture_filename_extractor>
> texture_flyweight;
int main()
{
/* texture filenames */
const char* texture_filenames[]={
"grass.texture","sand.texture","water.texture","wood.texture",
"granite.texture","cotton.texture","concrete.texture","carpet.texture"
};
const int num_texture_filenames=
sizeof(texture_filenames)/sizeof(texture_filenames[0]);
/* create a massive vector of textures */
std::cout<<"creating flyweights...\n"<<std::endl;
std::vector<texture_flyweight> textures;
for(int i=0;i<50000;++i){
textures.push_back(
texture_flyweight(texture_filenames[std::rand()%num_texture_filenames]));
}
/* Just for the sake of making use of the key extractor,
* assign some flyweights with texture objects rather than strings.
*/
for(int j=0;j<50000;++j){
textures.push_back(
texture_flyweight(
textures[std::rand()%textures.size()].get()));
}
std::cout<<"\n"<<textures.size()<<" flyweights created\n"<<std::endl;
return 0;
}

312
example/perf.cpp Normal file
View File

@@ -0,0 +1,312 @@
/* Boost.Flyweight example of performance comparison.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/flyweight/flyweight.hpp>
#include <boost/flyweight/hashed_factory.hpp>
#include <boost/flyweight/set_factory.hpp>
#include <boost/flyweight/static_holder.hpp>
#include <boost/flyweight/simple_locking.hpp>
#include <boost/flyweight/refcounted.hpp>
#include <boost/flyweight/no_tracking.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/tokenizer.hpp>
#include <algorithm>
#include <cstddef>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <iostream>
#include <numeric>
#include <sstream>
#include <string>
#include <vector>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
using ::clock;
using ::clock_t;
using ::exit;
}
#endif
using namespace boost::flyweights;
/* Instrumented allocator family keeping track of the memory in
* current use.
*/
std::size_t count_allocator_mem=0;
template<typename T>
class count_allocator
{
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template<class U>struct rebind{typedef count_allocator<U> other;};
count_allocator(){}
count_allocator(const count_allocator<T>&){}
template<class U>count_allocator(const count_allocator<U>&,int=0){}
pointer address(reference x)const{return &x;}
const_pointer address(const_reference x)const{return &x;}
pointer allocate(size_type n,const void* =0)
{
pointer p=(T*)(new char[n*sizeof(T)]);
count_allocator_mem+=n*sizeof(T);
return p;
}
void deallocate(void* p,size_type n)
{
count_allocator_mem-=n*sizeof(T);
delete [](char *)p;
}
size_type max_size() const{return (size_type )(-1);}
void construct(pointer p,const T& val){new(p)T(val);}
void destroy(pointer p){p->~T();}
friend bool operator==(const count_allocator&,const count_allocator&)
{
return true;
}
friend bool operator!=(const count_allocator&,const count_allocator&)
{
return false;
}
};
template<>
class count_allocator<void>
{
public:
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
template<class U>struct rebind{typedef count_allocator<U> other;};
};
/* Define some count_allocator-based types and Boost.Flyweight components */
typedef std::basic_string<
char,std::char_traits<char>,count_allocator<char>
> count_string;
typedef hashed_factory<
boost::hash<boost::mpl::_2>,
std::equal_to<boost::mpl::_2>,
count_allocator<boost::mpl::_1>
> count_hashed_factory;
typedef set_factory<
std::less<boost::mpl::_2>,
count_allocator<boost::mpl::_1>
> count_set_factory;
/* Some additional utilities used by the test routine */
class timer
{
public:
timer(){restart();}
void restart(){t=std::clock();}
void time(const char* str)
{
std::cout<<str<<": "<<(double)(std::clock()-t)/CLOCKS_PER_SEC<<" s\n";
}
private:
std::clock_t t;
};
template<typename T>
struct is_flyweight:
boost::mpl::false_{};
template<
typename T,
typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5
>
struct is_flyweight<flyweight<T,Arg1,Arg2,Arg3,Arg4,Arg5> >:
boost::mpl::true_{};
struct length_adder
{
std::size_t operator()(std::size_t n,const count_string& x)const
{
return n+x.size();
}
};
/* Measure time and memory performance for a String, which is assumed
* to be either a plain string type or a string flyweight.
*/
template<typename String>
struct test
{
static std::size_t run(const std::string& file)
{
typedef std::vector<String,count_allocator<String> > count_vector;
/* Define a tokenizer on std::istreambuf. */
typedef std::istreambuf_iterator<char> char_iterator;
typedef boost::tokenizer<
boost::char_separator<char>,
char_iterator
> tokenizer;
std::ifstream ifs(file.c_str());
if(!ifs){
std::cout<<"can't open "<<file<<std::endl;
std::exit(EXIT_FAILURE);
}
/* Initialization; tokenize using space and common punctuaction as
* separators, and keeping the separators.
*/
timer t;
tokenizer tok=tokenizer(
char_iterator(ifs),char_iterator(),
boost::char_separator<char>(
"",
"\t\n\r !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"));
count_vector txt;
for(tokenizer::iterator it=tok.begin();it!=tok.end();++it){
txt.push_back(String(it->c_str()));
}
t.time("initialization time");
/* Assignment */
t.restart();
count_vector txt2;
for(int i=0;i<10;++i){
txt2.insert(txt2.end(),txt.begin(),txt.end());
}
t.time("assignment time");
/* Equality comparison */
t.restart();
std::size_t c=0;
for(int i=0;i<100;++i){
c+=std::count(txt.begin(),txt.end(),txt[c%txt.size()]);
}
t.time("equality comparison time");
/* Value access */
t.restart();
std::size_t s=0;
for(int i=0;i<20;++i){
s+=std::accumulate(txt2.begin(),txt2.end(),s,length_adder());
}
t.time("value access time");
std::cout<<"bytes used: "<<count_allocator_mem;
if(is_flyweight<String>::value){
std::size_t flyweight_mem=(txt.capacity()+txt2.capacity())*sizeof(String);
std::cout<<"= flyweights("<<flyweight_mem
<<")+values("<<count_allocator_mem-flyweight_mem<<")";
}
std::cout<<"\n";
return c+s;
}
};
/* table of test cases for the user to select from */
struct test_case
{
const char* name;
std::size_t (*test)(const std::string&);
};
test_case test_table[]=
{
{
"simple string",
test<count_string>::run
},
{
"flyweight, hashed factory",
test<flyweight<count_string,count_hashed_factory> >::run
},
{
"flyweight, hashed factory, no tracking",
test<flyweight<count_string,count_hashed_factory,no_tracking> >::run
},
{
"flyweight, set-based factory",
test<flyweight<count_string,count_set_factory> >::run
},
{
"flyweight, set-based factory, no tracking",
test<flyweight<count_string,count_set_factory,no_tracking> >::run
}
};
const int num_test_cases=sizeof(test_table)/sizeof(test_case);
int main()
{
try{
for(int i=0;i<num_test_cases;++i){
std::cout<<i+1<<". "<<test_table[i].name<<"\n";
}
int option=-1;
for(;;){
std::cout<<"select option, enter to exit: ";
std::string str;
std::getline(std::cin,str);
if(str.empty())std::exit(EXIT_SUCCESS);
std::istringstream istr(str);
istr>>option;
if(option>=1&&option<=num_test_cases){
--option; /* pass from 1-based menu to 0-based test_table */
break;
}
}
std::cout<<"enter file name: ";
std::string file;
std::getline(std::cin,file);
std::size_t result=0;
result=test_table[option].test(file);
}
catch(const std::exception& e){
std::cout<<"error: "<<e.what()<<"\n";
}
return 0;
}

View File

@@ -0,0 +1,22 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_HPP
#define BOOST_FLYWEIGHT_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/flyweight/flyweight.hpp>
#include <boost/flyweight/hashed_factory.hpp>
#include <boost/flyweight/refcounted.hpp>
#include <boost/flyweight/simple_locking.hpp>
#include <boost/flyweight/static_holder.hpp>
#endif

View File

@@ -0,0 +1,88 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_ASSOC_CONTAINER_FACTORY_HPP
#define BOOST_FLYWEIGHT_ASSOC_CONTAINER_FACTORY_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/assoc_container_factory_fwd.hpp>
#include <boost/flyweight/factory_tag.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
/* Factory class using a given associative container.
*/
namespace boost{
namespace flyweights{
template<typename Container>
class assoc_container_factory_class:public factory_marker
{
public:
typedef typename Container::iterator handle_type;
typedef typename Container::value_type entry_type;
handle_type insert(const entry_type& x)
{
return cont.insert(x).first;
}
void erase(handle_type h)
{
cont.erase(h);
}
static const entry_type& entry(handle_type h){return *h;}
private:
Container cont;
public:
typedef assoc_container_factory_class type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,assoc_container_factory_class,(Container))
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
/* This is preferred to deriving from factory_marker since checking for
* derivation forces the instantiation of the specifier, which is not
* needed when the specifier is a placeholder expression.
*/
template<typename Container>
struct is_factory<assoc_container_factory_class<Container> >:
boost::mpl::true_{};
#endif
/* assoc_container_factory_class specifier */
template<
typename ContainerSpecifier
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION_DEF
>
struct assoc_container_factory:factory_marker
{
template<typename Entry,typename Key>
struct apply
{
typedef assoc_container_factory_class<
typename mpl::apply2<ContainerSpecifier,Entry,Key>::type
> type;
};
};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,35 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_ASSOC_CONTAINER_FACTORY_FWD_HPP
#define BOOST_FLYWEIGHT_ASSOC_CONTAINER_FACTORY_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/flyweight/detail/not_placeholder_expr.hpp>
namespace boost{
namespace flyweights{
template<typename Container>
class assoc_container_factory_class;
template<
typename ContainerSpecifier
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION
>
struct assoc_container_factory;
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,58 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_DETAIL_DEFAULT_VALUE_POLICY_HPP
#define BOOST_FLYWEIGHT_DETAIL_DEFAULT_VALUE_POLICY_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/flyweight/detail/value_tag.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
/* Default value policy: the key is the same as the value.
*/
namespace boost{
namespace flyweights{
namespace detail{
template<typename Value>
struct default_value_policy:value_marker
{
typedef Value key_type;
typedef Value value_type;
struct rep_type
{
/* template ctors */
#define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit rep_type
#define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
:x(BOOST_PP_ENUM_PARAMS(n,t)){}
#include <boost/flyweight/detail/perfect_fwd.hpp>
operator const value_type&()const{return x;}
value_type x;
};
static void construct_value(const rep_type&){}
static void copy_value(const rep_type&){}
};
} /* namespace flyweights::detail */
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,75 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
/* no include guards */
#include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/for_each_product.hpp>
#include <boost/preprocessor/seq/size.hpp>
#define BOOST_FLYWEIGHT_CONST(b) BOOST_PP_CAT(BOOST_FLYWEIGHT_CONST,b)
#define BOOST_FLYWEIGHT_CONST0
#define BOOST_FLYWEIGHT_CONST1 const
/* if mask[n]==0 --> Tn& tn
* if mask[n]==1 --> const Tn& tn
*/
#define BOOST_FLYWEIGHT_PERFECT_FWD_ARG(z,n,mask) \
BOOST_FLYWEIGHT_CONST(BOOST_PP_SEQ_ELEM(n,mask)) \
BOOST_PP_CAT(T,n)& BOOST_PP_CAT(t,n)
/* overload accepting size(mask) args, where the template args are
* marked const or not according to the given mask (a seq of 0 or 1)
*/
#define BOOST_FLYWEIGHT_PERFECT_FWD(r,mask) \
template<BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(mask),typename T)> \
BOOST_FLYWEIGHT_PERFECT_FWD_NAME( \
BOOST_PP_ENUM( \
BOOST_PP_SEQ_SIZE(mask),BOOST_FLYWEIGHT_PERFECT_FWD_ARG,mask)) \
BOOST_FLYWEIGHT_PERFECT_FWD_BODY(BOOST_PP_SEQ_SIZE(mask))
#define BOOST_FLYWEIGHT_01(z,n,_) ((0)(1))
/* Perfect forwarding overloads accepting 1 to n args */
#define BOOST_FLYWEIGHT_PERFECT_FWDS_N(z,n,_) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
BOOST_FLYWEIGHT_PERFECT_FWD, \
BOOST_PP_REPEAT(n,BOOST_FLYWEIGHT_01,~))
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
BOOST_PP_REPEAT_FROM_TO( \
1,BOOST_PP_ADD(BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS,1), \
BOOST_FLYWEIGHT_PERFECT_FWDS_N,~)
/* generate the overloads */
BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS
/* clean up */
#undef BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS
#undef BOOST_FLYWEIGHT_01
#undef BOOST_FLYWEIGHT_PERFECT_FWD
#undef BOOST_FLYWEIGHT_PERFECT_FWD_ARG
#undef BOOST_FLYWEIGHT_CONST1
#undef BOOST_FLYWEIGHT_CONST0
#undef BOOST_FLYWEIGHT_CONST
/* user supplied argument macros */
#undef BOOST_FLYWEIGHT_PERFECT_FWD_BODY
#undef BOOST_FLYWEIGHT_PERFECT_FWD_NAME

View File

@@ -0,0 +1,256 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_DETAIL_FLYWEIGHT_CORE_HPP
#define BOOST_FLYWEIGHT_DETAIL_FLYWEIGHT_CORE_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/flyweight/detail/handle_factory_adaptor.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
#pragma warning(push)
#pragma warning(disable:4101) /* unreferenced local vars */
#endif
/* flyweight_core provides the inner implementation of flyweight<> by
* weaving together a value policy, a flyweight factory, a holder for the
* factory,a tracking policy and a locking policy.
*/
namespace boost{
namespace flyweights{
namespace detail{
template<
typename ValuePolicy,typename Tag,typename TrackingPolicy,
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
>
class flyweight_core;
template<
typename ValuePolicy,typename Tag,typename TrackingPolicy,
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
>
struct flyweight_core_tracking_helper
{
private:
typedef flyweight_core<
ValuePolicy,Tag,TrackingPolicy,
FactorySpecifier,LockingPolicy,
HolderSpecifier
> core;
typedef typename core::handle_type handle_type;
typedef typename core::entry_type entry_type;
public:
static const entry_type& entry(const handle_type& h)
{
return core::entry(h);
}
template<typename Checker>
static void erase(const handle_type& h,Checker check)
{
typedef typename core::lock_type lock_type;
lock_type lock(core::mutex());
if(check(h))core::factory().erase(h);
}
};
template<
typename ValuePolicy,typename Tag,typename TrackingPolicy,
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
>
class flyweight_core
{
public:
typedef typename ValuePolicy::key_type key_type;
typedef typename ValuePolicy::value_type value_type;
typedef typename ValuePolicy::rep_type rep_type;
typedef typename mpl::apply2<
typename TrackingPolicy::entry_type,
rep_type,
key_type
>::type entry_type;
typedef typename mpl::apply2<
FactorySpecifier,
entry_type,
key_type
>::type base_factory_type;
typedef typename mpl::apply2<
typename TrackingPolicy::handle_type,
typename base_factory_type::handle_type,
flyweight_core_tracking_helper<
ValuePolicy,Tag,TrackingPolicy,
FactorySpecifier,LockingPolicy,
HolderSpecifier
>
>::type handle_type;
typedef handle_factory_adaptor<
base_factory_type,
handle_type,entry_type
> factory_type;
typedef typename LockingPolicy::mutex_type mutex_type;
typedef typename LockingPolicy::lock_type lock_type;
static bool init()
{
if(static_initializer)return true;
else{
holder_arg& a=holder_type::get();
static_factory_ptr=&a.factory;
static_mutex_ptr=&a.mutex;
static_initializer=(static_factory_ptr!=0);
return static_initializer;
}
}
/* insert overloads*/
#define BOOST_FLYWEIGHT_PERFECT_FWD_NAME static handle_type insert
#define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
{ \
return insert_rep(rep_type(BOOST_PP_ENUM_PARAMS(n,t))); \
}
#include <boost/flyweight/detail/perfect_fwd.hpp>
static handle_type insert(const value_type& x){return insert_value(x);}
static handle_type insert(value_type& x){return insert_value(x);}
static const entry_type& entry(const handle_type& h)
{
return factory().entry(h);
}
static const value_type& value(const handle_type& h)
{
return static_cast<const rep_type&>(entry(h));
}
static const key_type& key(const handle_type& h)
{
return static_cast<const rep_type&>(entry(h));
}
static factory_type& factory()
{
return *static_factory_ptr;
}
static mutex_type& mutex()
{
return *static_mutex_ptr;
}
private:
struct holder_arg
{
factory_type factory;
mutex_type mutex;
};
typedef typename mpl::apply1<
HolderSpecifier,
holder_arg
>::type holder_type;
static handle_type insert_rep(const rep_type& x)
{
init();
entry_type e(x);
lock_type lock(mutex());
handle_type h(factory().insert(e));
BOOST_TRY{
ValuePolicy::construct_value(
static_cast<const rep_type&>(entry(h)));
}
BOOST_CATCH(...){
factory().erase(h);
BOOST_RETHROW;
}
BOOST_CATCH_END
return h;
}
static handle_type insert_value(const value_type& x)
{
init();
entry_type e=entry_type(rep_type(x));
lock_type lock(mutex());
handle_type h(factory().insert(e));
BOOST_TRY{
ValuePolicy::copy_value(
static_cast<const rep_type&>(entry(h)));
}
BOOST_CATCH(...){
factory().erase(h);
BOOST_RETHROW;
}
BOOST_CATCH_END
return h;
}
static bool static_initializer;
static factory_type* static_factory_ptr;
static mutex_type* static_mutex_ptr;
};
template<
typename ValuePolicy,typename Tag,typename TrackingPolicy,
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
>
bool
flyweight_core<
ValuePolicy,Tag,TrackingPolicy,
FactorySpecifier,LockingPolicy,HolderSpecifier>::static_initializer=
flyweight_core<
ValuePolicy,Tag,TrackingPolicy,
FactorySpecifier,LockingPolicy,HolderSpecifier>::init();
template<
typename ValuePolicy,typename Tag,typename TrackingPolicy,
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
>
typename flyweight_core<
ValuePolicy,Tag,TrackingPolicy,
FactorySpecifier,LockingPolicy,HolderSpecifier>::factory_type*
flyweight_core<
ValuePolicy,Tag,TrackingPolicy,
FactorySpecifier,LockingPolicy,HolderSpecifier>::static_factory_ptr=0;
template<
typename ValuePolicy,typename Tag,typename TrackingPolicy,
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
>
typename flyweight_core<
ValuePolicy,Tag,TrackingPolicy,
FactorySpecifier,LockingPolicy,HolderSpecifier>::mutex_type*
flyweight_core<
ValuePolicy,Tag,TrackingPolicy,
FactorySpecifier,LockingPolicy,HolderSpecifier>::static_mutex_ptr=0;
} /* namespace flyweights::detail */
} /* namespace flyweights */
} /* namespace boost */
#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
#pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,48 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_DETAIL_HANDLE_FACTORY_ADAPTOR_HPP
#define BOOST_FLYWEIGHT_DETAIL_HANDLE_FACTORY_ADAPTOR_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
/* Given a Factory and a Handle type constructible from and implicitly
* convertible to Factory::handle_type, handle_factory_adaptor
* adapts Factory to present Handle as the associated handle_type.
*/
namespace boost{
namespace flyweights{
namespace detail{
template<typename Factory,typename Handle,typename Entry>
struct handle_factory_adaptor:Factory
{
public:
typedef Handle handle_type;
handle_type insert(const Entry& x)
{
return static_cast<handle_type>(base().insert(x));
}
private:
Factory& base(){return *this;}
};
} /* namespace flyweights::detail */
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,58 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_DETAIL_NOT_PLACEHOLDER_EXPR_HPP
#define BOOST_FLYWEIGHT_DETAIL_NOT_PLACEHOLDER_EXPR_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
/* BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION can be inserted at the end
* of a class template parameter declaration:
* template<
* typename X0,...,typename Xn
* BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION
* >
* struct foo...
* to prevent instantiations from being treated as MPL placeholder
* expressions in the presence of placeholder arguments; this is useful
* to avoid masking of a metafunction class nested ::apply during
* MPL invocation.
*/
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(__GNUC__, <4)||\
BOOST_WORKAROUND(__GNUC__,==4)&&(__GNUC_MINOR__<2)
/* The default trick on which the macro is based, namely adding a int=0
* defaulted template parameter, does not work in GCC prior to 4.2 due to
* an unfortunate compiler non-standard extension, as explained in
* http://lists.boost.org/boost-users/2007/07/29866.php
* We resort to an uglier technique, adding defaulted template parameters
* so as to exceed BOOST_MPL_LIMIT_METAFUNCTION_ARITY.
*/
#include <boost/mpl/limits/arity.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#define BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION \
BOOST_PP_ENUM_TRAILING_PARAMS( \
BOOST_MPL_LIMIT_METAFUNCTION_ARITY,typename=int BOOST_PP_INTERCEPT)
#define BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION_DEF \
BOOST_PP_ENUM_TRAILING_PARAMS( \
BOOST_MPL_LIMIT_METAFUNCTION_ARITY,typename BOOST_PP_INTERCEPT)
#else
#define BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION ,int=0
#define BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION_DEF ,int
#endif
#endif

View File

@@ -0,0 +1,28 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
/* Brute force implementation of perfect forwarding overloads.
* Usage: include after having defined the argument macros:
* BOOST_FLYWEIGHT_PERFECT_FWD_NAME
* BOOST_FLYWEIGHT_PERFECT_FWD_BODY
*/
/* This user_definable macro limits the maximum number of arguments to
* be perfect forwarded. Beware combinatorial explosion: manual perfect
* forwarding for n arguments produces 2^n distinct overloads.
*/
#if !defined(BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS)
#define BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS 5
#endif
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS<=5
#include <boost/flyweight/detail/pp_perfect_fwd.hpp>
#else
#include <boost/flyweight/detail/dyn_perfect_fwd.hpp>
#endif

View File

@@ -0,0 +1,153 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
/* no include guards */
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=1
#define BOOST_FLYWEIGHT_PERFECT_FWDS_1 \
template<typename T0> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(1)\
template<typename T0> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(1)
#endif
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=2
#define BOOST_FLYWEIGHT_PERFECT_FWDS_2 \
template<typename T0,typename T1> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(2)\
template<typename T0,typename T1> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(2)\
template<typename T0,typename T1> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(2)\
template<typename T0,typename T1> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(2)
#endif
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=3
#define BOOST_FLYWEIGHT_PERFECT_FWDS_3 \
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)
#endif
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=4
#define BOOST_FLYWEIGHT_PERFECT_FWDS_4 \
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)
#endif
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=5
#define BOOST_FLYWEIGHT_PERFECT_FWDS_5 \
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)
#endif
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==0
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS
#elif BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==1
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
BOOST_FLYWEIGHT_PERFECT_FWDS_1
#elif BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==2
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
BOOST_FLYWEIGHT_PERFECT_FWDS_1 \
BOOST_FLYWEIGHT_PERFECT_FWDS_2
#elif BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==3
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
BOOST_FLYWEIGHT_PERFECT_FWDS_1 \
BOOST_FLYWEIGHT_PERFECT_FWDS_2 \
BOOST_FLYWEIGHT_PERFECT_FWDS_3
#elif BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==4
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
BOOST_FLYWEIGHT_PERFECT_FWDS_1 \
BOOST_FLYWEIGHT_PERFECT_FWDS_2 \
BOOST_FLYWEIGHT_PERFECT_FWDS_3 \
BOOST_FLYWEIGHT_PERFECT_FWDS_4
#else /* BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==5 */
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
BOOST_FLYWEIGHT_PERFECT_FWDS_1 \
BOOST_FLYWEIGHT_PERFECT_FWDS_2 \
BOOST_FLYWEIGHT_PERFECT_FWDS_3 \
BOOST_FLYWEIGHT_PERFECT_FWDS_4 \
BOOST_FLYWEIGHT_PERFECT_FWDS_5
#endif
/* generate the overloads */
BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS
/* clean up */
#undef BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=1
#undef BOOST_FLYWEIGHT_PERFECT_FWDS_1
#endif
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=2
#undef BOOST_FLYWEIGHT_PERFECT_FWDS_2
#endif
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=3
#undef BOOST_FLYWEIGHT_PERFECT_FWDS_3
#endif
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=4
#undef BOOST_FLYWEIGHT_PERFECT_FWDS_4
#endif
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=5
#undef BOOST_FLYWEIGHT_PERFECT_FWDS_5
#endif
/* user supplied argument macros */
#undef BOOST_FLYWEIGHT_PERFECT_FWD_NAME
#undef BOOST_FLYWEIGHT_PERFECT_FWD_BODY

View File

@@ -0,0 +1,81 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_DETAIL_PROCESS_ID_HPP
#define BOOST_FLYWEIGHT_DETAIL_PROCESS_ID_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp>
#if defined(BOOST_WINDOWS)&&!defined(BOOST_DISABLE_WIN32)
#if defined(BOOST_USE_WINDOWS_H)
#include <windows.h>
#else
namespace boost{
namespace flyweights{
namespace detail{
extern "C" __declspec(dllimport)
unsigned long __stdcall GetCurrentProcessId(void);
} /* namespace flyweights::detail */
} /* namespace flyweights */
} /* namespace boost */
#endif
namespace boost{
namespace flyweights{
namespace detail{
typedef unsigned long process_id_t;
inline process_id_t process_id()
{
return GetCurrentProcessId();
}
} /* namespace flyweights::detail */
} /* namespace flyweights */
} /* namespace boost */
#elif defined(BOOST_HAS_UNISTD_H)
#include <unistd.h>
namespace boost{
namespace flyweights{
namespace detail{
typedef pid_t process_id_t;
inline process_id_t process_id()
{
return ::getpid();
}
} /* namespace flyweights::detail */
} /* namespace flyweights */
} /* namespace boost */
#else
#error Unknown platform
#endif
#endif

View File

@@ -0,0 +1,91 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_DETAIL_RECURSIVE_LW_MUTEX_HPP
#define BOOST_FLYWEIGHT_DETAIL_RECURSIVE_LW_MUTEX_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
/* Recursive lightweight mutex. Relies entirely on
* boost::detail::lightweight_mutex, except in Pthreads, where we
* explicitly use the PTHREAD_MUTEX_RECURSIVE attribute
* (lightweight_mutex uses the default mutex type instead).
*/
#include <boost/config.hpp>
#if !defined(BOOST_HAS_PTHREADS)
#include <boost/detail/lightweight_mutex.hpp>
namespace boost{
namespace flyweights{
namespace detail{
typedef boost::detail::lightweight_mutex recursive_lightweight_mutex;
} /* namespace flyweights::detail */
} /* namespace flyweights */
} /* namespace boost */
#else
/* code shamelessly ripped from <boost/detail/lwm_pthreads.hpp> */
#include <boost/noncopyable.hpp>
#include <pthread.h>
namespace boost{
namespace flyweights{
namespace detail{
struct recursive_lightweight_mutex:noncopyable
{
recursive_lightweight_mutex()
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_,&attr);
pthread_mutexattr_destroy(&attr);
}
~recursive_lightweight_mutex(){pthread_mutex_destroy(&m_);}
struct scoped_lock;
friend struct scoped_lock;
struct scoped_lock:noncopyable
{
public:
scoped_lock(recursive_lightweight_mutex& m):m_(m.m_)
{
pthread_mutex_lock(&m_);
}
~scoped_lock(){pthread_mutex_unlock(&m_);}
private:
pthread_mutex_t& m_;
};
private:
pthread_mutex_t m_;
};
} /* namespace flyweights::detail */
} /* namespace flyweights */
} /* namespace boost */
#endif
#endif

View File

@@ -0,0 +1,50 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_DETAIL_VALUE_TAG_HPP
#define BOOST_FLYWEIGHT_DETAIL_VALUE_TAG_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/parameter/parameters.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
namespace boost{
namespace flyweights{
namespace detail{
/* Three ways to indicate that a given class T is a value policy:
* 1. Make it derived from value_marker.
* 2. Specialize is_value to evaluate to boost::mpl::true_.
* 3. Pass it as value<T> when defining a flyweight type.
*
* For the time being the interface of value policies is not public.
*/
struct value_marker{};
template<typename T>
struct is_value:is_base_and_derived<value_marker,T>
{};
template<typename T=parameter::void_>
struct value:parameter::template_keyword<value<>,T>
{};
} /* namespace flyweights::detail */
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,44 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_FACTORY_TAG_HPP
#define BOOST_FLYWEIGHT_FACTORY_TAG_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/parameter/parameters.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
namespace boost{
namespace flyweights{
/* Three ways to indicate that a given class T is a factory specifier:
* 1. Make it derived from factory_marker.
* 2. Specialize is_factory to evaluate to boost::mpl::true_.
* 3. Pass it as factory<T> when defining a flyweight type.
*/
struct factory_marker{};
template<typename T>
struct is_factory:is_base_and_derived<factory_marker,T>
{};
template<typename T=parameter::void_>
struct factory:parameter::template_keyword<factory<>,T>
{};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,407 @@
/* Flyweight class.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_FLYWEIGHT_HPP
#define BOOST_FLYWEIGHT_FLYWEIGHT_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/workaround.hpp>
#include <boost/flyweight/detail/default_value_policy.hpp>
#include <boost/flyweight/detail/flyweight_core.hpp>
#include <boost/flyweight/factory_tag.hpp>
#include <boost/flyweight/flyweight_fwd.hpp>
#include <boost/flyweight/locking_tag.hpp>
#include <boost/flyweight/simple_locking_fwd.hpp>
#include <boost/flyweight/static_holder_fwd.hpp>
#include <boost/flyweight/hashed_factory_fwd.hpp>
#include <boost/flyweight/holder_tag.hpp>
#include <boost/flyweight/refcounted_fwd.hpp>
#include <boost/flyweight/tag.hpp>
#include <boost/flyweight/tracking_tag.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/or.hpp>
#include <boost/parameter/binding.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/swap.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
#pragma warning(push)
#pragma warning(disable:4521) /* multiple copy ctors */
#endif
namespace boost{
namespace flyweights{
namespace detail{
/* Used for the detection of unmatched template args in a
* flyweight instantiation.
*/
struct unmatched_arg;
/* Boost.Parameter structures for use in flyweight.
* NB: these types are derived from instead of typedef'd to force their
* instantiation, which solves http://bugs.sun.com/view_bug.do?bug_id=6782987
* as found out by Simon Atanasyan.
*/
struct flyweight_signature:
parameter::parameters<
parameter::optional<
parameter::deduced<tag<> >,
detail::is_tag<boost::mpl::_>
>,
parameter::optional<
parameter::deduced<tracking<> >,
is_tracking<boost::mpl::_>
>,
parameter::optional<
parameter::deduced<factory<> >,
is_factory<boost::mpl::_>
>,
parameter::optional<
parameter::deduced<locking<> >,
is_locking<boost::mpl::_>
>,
parameter::optional<
parameter::deduced<holder<> >,
is_holder<boost::mpl::_>
>
>
{};
struct flyweight_unmatched_signature:
parameter::parameters<
parameter::optional<
parameter::deduced<
detail::unmatched_arg
>,
mpl::not_<
mpl::or_<
detail::is_tag<boost::mpl::_>,
is_tracking<boost::mpl::_>,
is_factory<boost::mpl::_>,
is_locking<boost::mpl::_>,
is_holder<boost::mpl::_>
>
>
>
>
{};
} /* namespace flyweights::detail */
template<
typename T,
typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5
>
class flyweight
{
private:
typedef typename mpl::if_<
detail::is_value<T>,
T,
detail::default_value_policy<T>
>::type value_policy;
typedef typename detail::
flyweight_signature::bind<
Arg1,Arg2,Arg3,Arg4,Arg5
>::type args;
typedef typename parameter::binding<
args,tag<>,mpl::na
>::type tag_type;
typedef typename parameter::binding<
args,tracking<>,refcounted
>::type tracking_policy;
typedef typename parameter::binding<
args,factory<>,hashed_factory<>
>::type factory_specifier;
typedef typename parameter::binding<
args,locking<>,simple_locking
>::type locking_policy;
typedef typename parameter::binding<
args,holder<>,static_holder
>::type holder_specifier;
typedef typename detail::
flyweight_unmatched_signature::bind<
Arg1,Arg2,Arg3,Arg4,Arg5
>::type unmatched_args;
typedef typename parameter::binding<
unmatched_args,detail::unmatched_arg,
detail::unmatched_arg
>::type unmatched_arg_detected;
/* You have passed a type in the specification of a flyweight type that
* could not be interpreted as a valid argument.
*/
BOOST_MPL_ASSERT_MSG(
(is_same<unmatched_arg_detected,detail::unmatched_arg>::value),
INVALID_ARGUMENT_TO_FLYWEIGHT,
(flyweight));
typedef detail::flyweight_core<
value_policy,tag_type,tracking_policy,
factory_specifier,locking_policy,
holder_specifier
> core;
typedef typename core::handle_type handle_type;
public:
typedef typename value_policy::key_type key_type;
typedef typename value_policy::value_type value_type;
/* static data initialization */
static bool init(){return core::init();}
class initializer
{
public:
initializer():b(init()){}
private:
bool b;
};
/* construct/copy/destroy */
flyweight():h(core::insert(key_type())){}
flyweight(const flyweight& x):h(x.h){}
flyweight(flyweight& x):h(x.h){}
/* template ctors */
#define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit flyweight
#define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
:h(core::insert(BOOST_PP_ENUM_PARAMS(n,t))){}
#include <boost/flyweight/detail/perfect_fwd.hpp>
flyweight& operator=(const flyweight x){h=x.h;return *this;}
flyweight& operator=(const value_type& x){return operator=(flyweight(x));}
/* convertibility to underlying type */
const key_type& get_key()const{return core::key(h);}
const value_type& get()const{return core::value(h);}
operator const value_type&()const{return get();}
/* exact type equality */
friend bool operator==(const flyweight& x,const flyweight& y)
{
return &x.get()==&y.get();
}
/* modifiers */
void swap(flyweight& x){boost::swap(h,x.h);}
private:
handle_type h;
};
#define BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(n) \
typename Arg##n##1,typename Arg##n##2,typename Arg##n##3, \
typename Arg##n##4,typename Arg##n##5
#define BOOST_FLYWEIGHT_TEMPL_ARGS(n) \
Arg##n##1,Arg##n##2,Arg##n##3,Arg##n##4,Arg##n##5
/* Comparison. Unlike exact type comparison defined above, intertype
* comparison just forwards to the underlying objects.
*/
template<
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
>
bool operator==(
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
{
return x.get()==y.get();
}
template<
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
>
bool operator<(
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
{
return x.get()<y.get();
}
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
template<
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
typename T2
>
bool operator==(
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y)
{
return x.get()==y;
}
template<
typename T1,
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
>
bool operator==(
const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
{
return x==y.get();
}
template<
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
typename T2
>
bool operator<(
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y)
{
return x.get()<y;
}
template<
typename T1,
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
>
bool operator<(
const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
{
return x<y.get();
}
#endif /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
/* rest of comparison operators */
#define BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(t,a1,a2) \
template<t> \
inline bool operator!=(const a1& x,const a2& y) \
{ \
return !(x==y); \
} \
\
template<t> \
inline bool operator>(const a1& x,const a2& y) \
{ \
return y<x; \
} \
\
template<t> \
inline bool operator>=(const a1& x,const a2& y) \
{ \
return !(x<y); \
} \
\
template<t> \
inline bool operator<=(const a1& x,const a2& y) \
{ \
return !(y<x); \
}
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
typename T1 BOOST_PP_COMMA()
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
typename T2 BOOST_PP_COMMA()
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
flyweight<
T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
>,
flyweight<
T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
>)
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
typename T1 BOOST_PP_COMMA()
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
typename T2,
flyweight<
T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
>,
T2)
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
typename T1 BOOST_PP_COMMA()
typename T2 BOOST_PP_COMMA()
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
T1,
flyweight<
T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
>)
#endif /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
/* specialized algorithms */
template<typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)>
void swap(
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x,
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& y)
{
x.swap(y);
}
template<
BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
BOOST_TEMPLATED_STREAM_COMMA
typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
>
BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& operator<<(
BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& out,
const flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x)
{
return out<<x.get();
}
template<
BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
BOOST_TEMPLATED_STREAM_COMMA
typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
>
BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& operator>>(
BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& in,
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x)
{
typedef typename flyweight<
T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)
>::value_type value_type;
/* value_type need not be default ctble but must be copy ctble */
value_type t(x.get());
in>>t;
x=t;
return in;
}
} /* namespace flyweights */
} /* namespace boost */
#undef BOOST_FLYWEIGHT_COMPLETE_COMP_OPS
#undef BOOST_FLYWEIGHT_TEMPL_ARGS
#undef BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS
#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
#pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,166 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_FLYWEIGHT_FWD_HPP
#define BOOST_FLYWEIGHT_FLYWEIGHT_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/templated_streams.hpp>
#include <boost/parameter/parameters.hpp>
#include <boost/preprocessor/punctuation/comma.hpp>
#include <iosfwd>
namespace boost{
namespace flyweights{
template<
typename T,
typename Arg1=parameter::void_,
typename Arg2=parameter::void_,
typename Arg3=parameter::void_,
typename Arg4=parameter::void_,
typename Arg5=parameter::void_
>
class flyweight;
#define BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(n) \
typename Arg##n##1,typename Arg##n##2,typename Arg##n##3, \
typename Arg##n##4,typename Arg##n##5
#define BOOST_FLYWEIGHT_TEMPL_ARGS(n) \
Arg##n##1,Arg##n##2,Arg##n##3,Arg##n##4,Arg##n##5
template<
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
>
bool operator==(
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y);
template<
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
>
bool operator<(
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y);
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
template<
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
typename T2
>
bool operator==(
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y);
template<
typename T1,
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
>
bool operator==(
const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y);
template<
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
typename T2
>
bool operator<(
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y);
template<
typename T1,
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
>
bool operator<(
const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y);
#endif /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
#define BOOST_FLYWEIGHT_COMPLETE_COMP_OPS_DECL(t,a1,a2) \
template<t> \
inline bool operator!=(const a1& x,const a2& y); \
\
template<t> \
inline bool operator>(const a1& x,const a2& y); \
\
template<t> \
inline bool operator>=(const a1& x,const a2& y); \
\
template<t> \
inline bool operator<=(const a1& x,const a2& y); \
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS_DECL(
typename T1 BOOST_PP_COMMA()
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
typename T2 BOOST_PP_COMMA()
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
flyweight<
T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
>,
flyweight<
T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
>)
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS_DECL(
typename T1 BOOST_PP_COMMA()
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
typename T2,
flyweight<
T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
>,
T2)
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS_DECL(
typename T1 BOOST_PP_COMMA()
typename T2 BOOST_PP_COMMA()
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
T1,
flyweight<
T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
>)
#endif /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
template<typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)>
inline void swap(
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x,
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& y);
template<
BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
BOOST_TEMPLATED_STREAM_COMMA
typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
>
inline BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& operator<<(
BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& out,
const flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x);
template<
BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
BOOST_TEMPLATED_STREAM_COMMA
typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
>
inline BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& operator>>(
BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& in,
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x);
} /* namespace flyweights */
using flyweights::flyweight;
} /* namespace boost */
#undef BOOST_FLYWEIGHT_COMPLETE_COMP_OPS_DECL
#undef BOOST_FLYWEIGHT_TEMPL_ARGS
#undef BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS
#endif

View File

@@ -0,0 +1,128 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_HASHED_FACTORY_HPP
#define BOOST_FLYWEIGHT_HASHED_FACTORY_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/factory_tag.hpp>
#include <boost/flyweight/hashed_factory_fwd.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
#include <boost/mpl/if.hpp>
/* Flyweight factory based on a hashed container implemented
* with Boost.MultiIndex.
*/
namespace boost{
namespace flyweights{
template<
typename Entry,typename Key,
typename Hash,typename Pred,typename Allocator
>
class hashed_factory_class:public factory_marker
{
struct index_list:
boost::mpl::vector1<
multi_index::hashed_unique<
multi_index::identity<Entry>,
typename boost::mpl::if_<
mpl::is_na<Hash>,
hash<Key>,
Hash
>::type,
typename boost::mpl::if_<
mpl::is_na<Pred>,
std::equal_to<Key>,
Pred
>::type
>
>
{};
typedef multi_index::multi_index_container<
Entry,
index_list,
typename boost::mpl::if_<
mpl::is_na<Allocator>,
std::allocator<Entry>,
Allocator
>::type
> container_type;
public:
typedef const Entry* handle_type;
handle_type insert(const Entry& x)
{
return &*cont.insert(x).first;
}
void erase(handle_type h)
{
cont.erase(cont.iterator_to(*h));
}
static const Entry& entry(handle_type h){return *h;}
private:
container_type cont;
public:
typedef hashed_factory_class type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(
5,hashed_factory_class,(Entry,Key,Hash,Pred,Allocator))
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
/* This is preferred to deriving from factory_marker since checking for
* derivation forces the instantiation of the specifier, which is not
* needed when the specifier is a placeholder expression.
*/
template<
typename Entry,typename Key,
typename Hash,typename Pred,typename Allocator
>
struct is_factory<hashed_factory_class<Entry,Key,Hash,Pred,Allocator> >:
boost::mpl::true_{};
#endif
/* hashed_factory_class specifier */
template<
typename Hash,typename Pred,typename Allocator
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION_DEF
>
struct hashed_factory:factory_marker
{
template<typename Entry,typename Key>
struct apply:
mpl::apply2<
hashed_factory_class<
boost::mpl::_1,boost::mpl::_2,Hash,Pred,Allocator
>,
Entry,Key
>
{};
};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,40 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_HASHED_FACTORY_FWD_HPP
#define BOOST_FLYWEIGHT_HASHED_FACTORY_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/detail/not_placeholder_expr.hpp>
#include <boost/mpl/aux_/na.hpp>
namespace boost{
namespace flyweights{
template<
typename Entry,typename Key,
typename Hash=mpl::na,typename Pred=mpl::na,typename Allocator=mpl::na
>
class hashed_factory_class;
template<
typename Hash=mpl::na,typename Pred=mpl::na,typename Allocator=mpl::na
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION
>
struct hashed_factory;
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,44 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_HOLDER_TAG_HPP
#define BOOST_FLYWEIGHT_HOLDER_TAG_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/parameter/parameters.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
namespace boost{
namespace flyweights{
/* Three ways to indicate that a given class T is a holder specifier:
* 1. Make it derived from holder_marker.
* 2. Specialize is_holder to evaluate to boost::mpl::true_.
* 3. Pass it as holder<T> when defining a flyweight type.
*/
struct holder_marker{};
template<typename T>
struct is_holder:is_base_and_derived<holder_marker,T>
{};
template<typename T=parameter::void_>
struct holder:parameter::template_keyword<holder<>,T>
{};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,202 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_INTERMODULE_HOLDER_HPP
#define BOOST_FLYWEIGHT_INTERMODULE_HOLDER_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/holder_tag.hpp>
#include <boost/flyweight/intermodule_holder_fwd.hpp>
#include <boost/flyweight/detail/process_id.hpp>
#include <boost/functional/hash.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
#include <cstdio>
#include <cstring>
#include <memory>
/* intermodule_holder_class guarantees a unique instance across all dynamic
* modules of a program.
*/
namespace boost{
namespace flyweights{
template<typename C>
struct intermodule_holder_class:holder_marker
{
static C& get()
{
static instantiator instance;
return instance.get();
}
private:
struct instantiator
{
instantiator():
mutex(interprocess::open_or_create,compute_mutex_name()),
seg(interprocess::open_or_create,compute_segment_name(),16384),
ppref(0),
pc(0)
{
/* Instance creation is done according to a two-phase protocol so
* that we call "new" in an unlocked situation, thus minimizing the
* chance of leaving dangling locks due to catastrophic failure.
*/
{
interprocess::scoped_lock<interprocess::named_mutex> lock(mutex);
ppref=seg.find_or_construct<referenced_instance*>(
typeid(C).name())((referenced_instance*)0);
if(*ppref){
/* As in some OSes Boost.Interprocess memory segments can outlive
* their associated processes, there is a possibility that we
* retrieve a dangling pointer (coming from a previous aborted run,
* for instance). Try to protect against this by checking that
* the contents of the pointed object are consistent.
*/
if(std::strcmp(segment_name,(*ppref)->segment_name)!=0){
*ppref=0; /* dangling pointer! */
}
else ++((*ppref)->ref);
}
}
if(!*ppref){
std::auto_ptr<referenced_instance> apc(
new referenced_instance(segment_name));
interprocess::scoped_lock<interprocess::named_mutex> lock(mutex);
ppref=seg.find_or_construct<referenced_instance*>(
typeid(C).name())((referenced_instance*)0);
if(!*ppref)*ppref=apc.release();
++((*ppref)->ref);
}
pc=&(*ppref)->c;
}
~instantiator()
{
/* As in construction time, actual deletion is performed outside the
* lock to avoid leaving the lock dangling in case of crash.
*/
referenced_instance* pref=0;
{
interprocess::scoped_lock<interprocess::named_mutex> lock(mutex);
if(--((*ppref)->ref)==0){
pref=*ppref;
*ppref=0;
}
}
if(pref)delete pref;
}
C& get()const{return *pc;}
private:
/* Although mutex and seg are system-wide, their names intend to
* make them specific for the current process and type, hence their
* containing process id and type id info.
*/
char mutex_name[128];
char segment_name[128];
const char* compute_mutex_name()
{
std::sprintf(
mutex_name,
"boost_flyweight_intermodule_holder_mutex_"
"%ld_%u_%u_%u_%u",
(long)detail::process_id(),
(unsigned)compute_hash(typeid(C).name(),0),
(unsigned)compute_hash(typeid(C).name(),1),
(unsigned)compute_hash(typeid(C).name(),2),
(unsigned)compute_hash(typeid(C).name(),3));
return mutex_name;
}
const char* compute_segment_name()
{
std::sprintf(
segment_name,
"boost_flyweight_intermodule_holder_segment_"
"%ld_%u_%u_%u_%u",
(long)detail::process_id(),
(unsigned)compute_hash(typeid(C).name(),0),
(unsigned)compute_hash(typeid(C).name(),1),
(unsigned)compute_hash(typeid(C).name(),2),
(unsigned)compute_hash(typeid(C).name(),3));
return segment_name;
}
static std::size_t compute_hash(const char* str,std::size_t off)
{
std::size_t len=std::strlen(str);
if(off>len)off=len;
return hash_range(str+off,str+len);
}
interprocess::named_mutex mutex;
interprocess::managed_shared_memory seg;
struct referenced_instance
{
referenced_instance(const char* segment_name_):ref(0)
{
strcpy(segment_name,segment_name_);
}
~referenced_instance(){segment_name[0]='\0';}
char segment_name[128]; /* used to detect dangling pointers */
mutable long ref;
C c;
}** ppref;
C* pc;
};
public:
typedef intermodule_holder_class type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,intermodule_holder_class,(C))
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
/* This is preferred to deriving from holder_marker since checking for
* derivation forces the instantiation of the specifier, which is not
* needed when the specifier is a placeholder expression.
*/
template<typename C>
struct is_holder<intermodule_holder_class<C> >:boost::mpl::true_{};
#endif
/* intermodule_holder_class specifier */
struct intermodule_holder:holder_marker
{
template<typename C>
struct apply
{
typedef intermodule_holder_class<C> type;
};
};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,29 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_INTERMODULE_HOLDER_FWD_HPP
#define BOOST_FLYWEIGHT_INTERMODULE_HOLDER_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace flyweights{
template<typename C>
struct intermodule_holder_class;
struct intermodule_holder;
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,238 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_KEY_VALUE_HPP
#define BOOST_FLYWEIGHT_KEY_VALUE_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/flyweight/detail/value_tag.hpp>
#include <boost/flyweight/key_value_fwd.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/is_same.hpp>
#include <new>
/* key-value policy: flywewight lookup is based on Key, which also serves
* to construct Value only when needed (new factory entry). key_value is
* used to avoid the construction of temporary values when such construction
* is expensive.
* Optionally, KeyFromValue extracts the key from a value, which
* is needed in expressions like this:
*
* typedef flyweight<key_value<Key,Value> > fw_t;
* fw_t fw;
* Value v;
* fw=v; // no key explicitly given
*
* If no KeyFromValue is provided, this latter expression fails to compile.
*/
namespace boost{
namespace flyweights{
namespace detail{
template<typename Key,typename Value,typename KeyFromValue>
struct optimized_key_value:value_marker
{
typedef Key key_type;
typedef Value value_type;
class rep_type
{
public:
/* template ctors */
#define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit rep_type
#define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
:value_ptr(0) \
{ \
new(spc_ptr())key_type(BOOST_PP_ENUM_PARAMS(n,t)); \
}
#include <boost/flyweight/detail/perfect_fwd.hpp>
rep_type(const value_type& x):value_ptr(&x){}
rep_type(const rep_type& x):value_ptr(x.value_ptr)
{
if(!x.value_ptr)new(key_ptr())key_type(*x.key_ptr());
}
~rep_type()
{
if(!value_ptr) key_ptr()->~key_type();
else if(value_cted())value_ptr->~value_type();
}
operator const key_type&()const
{
if(value_ptr)return key_from_value(*value_ptr);
else return *key_ptr();
}
operator const value_type&()const
{
/* This is always called after construct_value() or copy_value(),
* so we access spc directly rather than through value_ptr to
* save us an indirection.
*/
return *static_cast<value_type*>(spc_ptr());
}
private:
friend struct optimized_key_value;
void* spc_ptr()const{return static_cast<void*>(&spc);}
bool value_cted()const{return value_ptr==spc_ptr();}
key_type* key_ptr()const
{
return static_cast<key_type*>(static_cast<void*>(&spc));
}
static const key_type& key_from_value(const value_type& x)
{
KeyFromValue k;
return k(x);
}
void construct_value()const
{
if(!value_cted()){
/* value_ptr must be ==0, oherwise copy_value would have been called */
key_type k(*key_ptr());
key_ptr()->~key_type();
value_ptr= /* guarantees key won't be re-dted at ~rep_type if the */
static_cast<value_type*>(spc_ptr())+1; /* next statement throws */
value_ptr=new(spc_ptr())value_type(k);
}
}
void copy_value()const
{
if(!value_cted())value_ptr=new(spc_ptr())value_type(*value_ptr);
}
mutable typename boost::aligned_storage<
(sizeof(key_type)>sizeof(value_type))?
sizeof(key_type):sizeof(value_type),
(boost::alignment_of<key_type>::value >
boost::alignment_of<value_type>::value)?
boost::alignment_of<key_type>::value:
boost::alignment_of<value_type>::value
>::type spc;
mutable const value_type* value_ptr;
};
static void construct_value(const rep_type& r)
{
r.construct_value();
}
static void copy_value(const rep_type& r)
{
r.copy_value();
}
};
template<typename Key,typename Value>
struct regular_key_value:value_marker
{
typedef Key key_type;
typedef Value value_type;
class rep_type
{
public:
/* template ctors */
#define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit rep_type
#define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
:key(BOOST_PP_ENUM_PARAMS(n,t)),value_ptr(0){}
#include <boost/flyweight/detail/perfect_fwd.hpp>
rep_type(const value_type& x):key(no_key_from_value_failure()){}
rep_type(const rep_type& x):key(x.key),value_ptr(0){}
~rep_type()
{
if(value_ptr)value_ptr->~value_type();
}
operator const key_type&()const{return key;}
operator const value_type&()const
{
/* This is always called after construct_value(),so we access spc
* directly rather than through value_ptr to save us an indirection.
*/
return *static_cast<value_type*>(spc_ptr());
}
private:
friend struct regular_key_value;
void* spc_ptr()const{return static_cast<void*>(&spc);}
struct no_key_from_value_failure
{
BOOST_MPL_ASSERT_MSG(
false,
NO_KEY_FROM_VALUE_CONVERSION_PROVIDED,
(key_type,value_type));
operator const key_type&()const;
};
void construct_value()const
{
if(!value_ptr)value_ptr=new(spc_ptr())value_type(key);
}
key_type key;
mutable typename boost::aligned_storage<
sizeof(value_type),
boost::alignment_of<value_type>::value
>::type spc;
mutable const value_type* value_ptr;
};
static void construct_value(const rep_type& r)
{
r.construct_value();
}
static void copy_value(const rep_type&){}
};
} /* namespace flyweights::detail */
template<typename Key,typename Value,typename KeyFromValue>
struct key_value:
mpl::if_<
is_same<KeyFromValue,no_key_from_value>,
detail::regular_key_value<Key,Value>,
detail::optimized_key_value<Key,Value,KeyFromValue>
>::type
{};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,29 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_KEY_VALUE_FWD_HPP
#define BOOST_FLYWEIGHT_KEY_VALUE_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace flyweights{
struct no_key_from_value;
template<typename Key,typename Value,typename KeyFromValue=no_key_from_value>
struct key_value;
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,44 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_LOCKING_TAG_HPP
#define BOOST_FLYWEIGHT_LOCKING_TAG_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/parameter/parameters.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
namespace boost{
namespace flyweights{
/* Three ways to indicate that a given class T is a locking policy:
* 1. Make it derived from locking_marker.
* 2. Specialize is_locking to evaluate to boost::mpl::true_.
* 3. Pass it as locking<T> when defining a flyweight type.
*/
struct locking_marker{};
template<typename T>
struct is_locking:is_base_and_derived<locking_marker,T>
{};
template<typename T=parameter::void_>
struct locking:parameter::template_keyword<locking<>,T>
{};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,36 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_NO_LOCKING_HPP
#define BOOST_FLYWEIGHT_NO_LOCKING_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/no_locking_fwd.hpp>
#include <boost/flyweight/locking_tag.hpp>
/* null locking policy */
namespace boost{
namespace flyweights{
struct no_locking:locking_marker
{
struct mutex_type{};
typedef mutex_type lock_type;
};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,26 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_NO_LOCKING_FWD_HPP
#define BOOST_FLYWEIGHT_NO_LOCKING_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace flyweights{
struct no_locking;
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,46 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_NO_TRACKING_HPP
#define BOOST_FLYWEIGHT_NO_TRACKING_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/no_tracking_fwd.hpp>
#include <boost/flyweight/tracking_tag.hpp>
/* Null tracking policy: elements are never erased from the factory.
*/
namespace boost{
namespace flyweights{
struct no_tracking:tracking_marker
{
struct entry_type
{
template<typename Value,typename Key>
struct apply{typedef Value type;};
};
struct handle_type
{
template<typename Handle,typename TrackingHelper>
struct apply{typedef Handle type;};
};
};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,26 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_NO_TRACKING_FWD_HPP
#define BOOST_FLYWEIGHT_NO_TRACKING_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace flyweights{
struct no_tracking;
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,152 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_REFCOUNTED_HPP
#define BOOST_FLYWEIGHT_REFCOUNTED_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/detail/atomic_count.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/flyweight/refcounted_fwd.hpp>
#include <boost/flyweight/tracking_tag.hpp>
#include <boost/utility/swap.hpp>
/* Refcounting tracking policy: values have an embedded ref count,
* when this goes down to zero the element is erased from the
* factory.
*/
namespace boost{
namespace flyweights{
namespace detail{
template<typename Value,typename Key>
class refcounted_value
{
public:
explicit refcounted_value(const Value& x_):
x(x_),ref(0)
{}
refcounted_value(const refcounted_value& r):
x(r.x),ref(0)
{}
~refcounted_value()
{
/* count()!=0 most likely indicates that the flyweight factory
* has been destructed before some of the flyweight objects using
* it. Check for static initialization order problems with this
* flyweight type.
*/
BOOST_ASSERT(count()==0);
}
refcounted_value& operator=(const refcounted_value& r)
{
x=r.x;
return *this;
}
operator const Value&()const{return x;}
operator const Key&()const{return x;}
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
private:
template<typename,typename> friend class refcounted_handle;
#endif
long count()const{return ref;}
void add_ref()const{++ref;}
bool release()const{return (--ref==0);}
private:
Value x;
mutable boost::detail::atomic_count ref;
};
template<typename Handle,typename TrackingHelper>
class refcounted_handle
{
public:
explicit refcounted_handle(const Handle& h_):h(h_)
{
TrackingHelper::entry(*this).add_ref();
}
refcounted_handle(const refcounted_handle& x):h(x.h)
{
TrackingHelper::entry(*this).add_ref();
}
refcounted_handle& operator=(refcounted_handle x)
{
swap(*this,x);
return *this;
}
~refcounted_handle()
{
if(TrackingHelper::entry(*this).release()){
TrackingHelper::erase(*this,check_erase);
}
}
operator const Handle&()const{return h;}
friend void swap(refcounted_handle& x, refcounted_handle& y)
{
boost::swap(x.h,y.h);
}
private:
static bool check_erase(const refcounted_handle& x)
{
return TrackingHelper::entry(x).count()==0;
}
Handle h;
};
} /* namespace flyweights::detail */
struct refcounted:tracking_marker
{
struct entry_type
{
template<typename Value,typename Key>
struct apply
{
typedef detail::refcounted_value<Value,Key> type;
};
};
struct handle_type
{
template<typename Handle,typename TrackingHelper>
struct apply
{
typedef detail::refcounted_handle<Handle,TrackingHelper> type;
};
};
};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,26 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_REFCOUNTED_FWD_HPP
#define BOOST_FLYWEIGHT_REFCOUNTED_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace flyweights{
struct refcounted;
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,96 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_SET_FACTORY_HPP
#define BOOST_FLYWEIGHT_SET_FACTORY_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/allocator_utilities.hpp>
#include <boost/flyweight/assoc_container_factory.hpp>
#include <boost/flyweight/factory_tag.hpp>
#include <boost/flyweight/set_factory_fwd.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
#include <boost/mpl/if.hpp>
#include <set>
/* Particularization of assoc_container_factory_class using a set.
*/
namespace boost{
namespace flyweights{
template<
typename Entry,typename Key,
typename Compare,typename Allocator
>
class set_factory_class:
public assoc_container_factory_class<
std::set<
Entry,
typename boost::mpl::if_<
mpl::is_na<Compare>,
std::less<Key>,
Compare
>::type,
typename boost::mpl::if_<
mpl::is_na<Allocator>,
std::allocator<Entry>,
Allocator
>::type
>
>
{
public:
typedef set_factory_class type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(
4,set_factory_class,(Entry,Key,Compare,Allocator))
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
/* This is preferred to deriving from factory_marker since checking for
* derivation forces the instantiation of the specifier, which is not
* needed when the specifier is a placeholder expression.
*/
template<
typename Entry,typename Key,
typename Compare,typename Allocator
>
struct is_factory<set_factory_class<Entry,Key,Compare,Allocator> >:
boost::mpl::true_{};
#endif
/* set_factory_class specifier */
template<
typename Compare,typename Allocator
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION_DEF
>
struct set_factory:factory_marker
{
template<typename Entry,typename Key>
struct apply:
mpl::apply2<
set_factory_class<
boost::mpl::_1,boost::mpl::_2,Compare,Allocator
>,
Entry,Key
>
{};
};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,40 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_SET_FACTORY_FWD_HPP
#define BOOST_FLYWEIGHT_SET_FACTORY_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/detail/not_placeholder_expr.hpp>
#include <boost/mpl/aux_/na.hpp>
namespace boost{
namespace flyweights{
template<
typename Entry,typename Key,
typename Compare=mpl::na,typename Allocator=mpl::na
>
class set_factory_class;
template<
typename Compare=mpl::na,typename Allocator=mpl::na
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION
>
struct set_factory;
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,37 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_SIMPLE_LOCKING_HPP
#define BOOST_FLYWEIGHT_SIMPLE_LOCKING_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/detail/recursive_lw_mutex.hpp>
#include <boost/flyweight/simple_locking_fwd.hpp>
#include <boost/flyweight/locking_tag.hpp>
/* simple locking policy based on native recursive mutexes */
namespace boost{
namespace flyweights{
struct simple_locking:locking_marker
{
typedef detail::recursive_lightweight_mutex mutex_type;
typedef mutex_type::scoped_lock lock_type;
};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,26 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_SIMPLE_LOCKING_FWD_HPP
#define BOOST_FLYWEIGHT_SIMPLE_LOCKING_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace flyweights{
struct simple_locking;
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,66 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_STATIC_HOLDER_HPP
#define BOOST_FLYWEIGHT_STATIC_HOLDER_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/static_holder_fwd.hpp>
#include <boost/flyweight/holder_tag.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
/* Simplest holder storing the T object as a local static variable.
*/
namespace boost{
namespace flyweights{
template<typename C>
struct static_holder_class:holder_marker
{
static C& get()
{
static C c;
return c;
}
typedef static_holder_class type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,static_holder_class,(C))
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
/* This is preferred to deriving from holder_marker since checking for
* derivation forces the instantiation of the specifier, which is not
* needed when the specifier is a placeholder expression.
*/
template<typename C>
struct is_holder<static_holder_class<C> >:boost::mpl::true_{};
#endif
/* static_holder_class specifier */
struct static_holder:holder_marker
{
template<typename C>
struct apply
{
typedef static_holder_class<C> type;
};
};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,29 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_STATIC_HOLDER_FWD_HPP
#define BOOST_FLYWEIGHT_STATIC_HOLDER_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace flyweights{
template<typename C>
struct static_holder_class;
struct static_holder;
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,46 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_TAG_HPP
#define BOOST_FLYWEIGHT_TAG_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/parameter/parameters.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
/* A type T can be used as a tag in the specification of a flyweight
* by passing it wrapped in the form tag<T>.
*/
namespace boost{
namespace flyweights{
namespace detail{
struct tag_marker{};
template<typename T>
struct is_tag:is_base_and_derived<tag_marker,T>
{};
} /* namespace flyweights::detail */
template<typename T=parameter::void_>
struct tag:parameter::template_keyword<tag<>,T>,detail::tag_marker
{};
} /* namespace flyweights */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,44 @@
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_TRACKING_TAG_HPP
#define BOOST_FLYWEIGHT_TRACKING_TAG_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/parameter/parameters.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
namespace boost{
namespace flyweights{
/* Three ways to indicate that a given class T is a tracking policy:
* 1. Make it derived from tracking_marker.
* 2. Specialize is_tracking to evaluate to boost::mpl::true_.
* 3. Pass it as tracking<T> when defining a flyweight type.
*/
struct tracking_marker{};
template<typename T>
struct is_tracking:is_base_and_derived<tracking_marker,T>
{};
template<typename T=parameter::void_>
struct tracking:parameter::template_keyword<tracking<>,T>
{};
} /* namespace flyweights */
} /* namespace boost */
#endif

20
index.html Normal file
View File

@@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
<!--
Copyright 2006 Joaquín M López Muñoz.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="refresh" content="0; URL=doc/index.html">
<title>Boost.Flyweight Documentation</title>
<link rel="stylesheet" href="doc/style.css" type="text/css">
</head>
<body>
Automatic redirection failed, please go to
<a href="doc/index.html">doc/index.html</a>
</body>
</html>

34
test/Jamfile.v2 Normal file
View File

@@ -0,0 +1,34 @@
# Boost.Flyweight tests Jamfile
#
# Copyright 2006-2008 Joaquín M López Muñoz.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# See http://www.boost.org/libs/flyweight for library home page.
project
: requirements
<os>LINUX:<threading>multi
;
test-suite "flyweight" :
[ run test_assoc_cont_factory.cpp test_assoc_cont_fact_main.cpp ]
[ run test_basic.cpp test_basic_main.cpp ]
[ run test_custom_factory.cpp test_custom_factory_main.cpp ]
[ run test_init.cpp test_init_main.cpp ]
[ run test_intermod_holder.cpp test_intermod_holder_main.cpp
intermod_holder_dll
: # command line
: # input files
: # requirements
<threading>multi ]
[ run test_multictor.cpp test_multictor_main.cpp ]
[ run test_no_locking.cpp test_no_locking_main.cpp ]
[ run test_no_tracking.cpp test_no_tracking_main.cpp ]
[ run test_set_factory.cpp test_set_factory_main.cpp ]
;
lib intermod_holder_dll : intermod_holder_dll.cpp :
<link>shared
<define>BOOST_FLYWEIGHT_TEST_INTERMOD_HOLDER_DLL_SOURCE=1 ;

87
test/heavy_objects.hpp Normal file
View File

@@ -0,0 +1,87 @@
/* Boost.Flyweight basic test template.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_TEST_HEAVY_OBJECTS_HPP
#define BOOST_FLYWEIGHT_TEST_HEAVY_OBJECTS_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/noncopyable.hpp>
#include <iosfwd>
#include <string>
struct texture
{
texture(const std::string& str=""):str(str){}
friend bool operator==(
const texture& x,const texture& y){return x.str==y.str;}
friend bool operator< (
const texture& x,const texture& y){return x.str< y.str;}
friend bool operator!=(
const texture& x,const texture& y){return x.str!=y.str;}
friend bool operator> (
const texture& x,const texture& y){return x.str> y.str;}
friend bool operator>=(
const texture& x,const texture& y){return x.str>=y.str;}
friend bool operator<=(
const texture& x,const texture& y){return x.str<=y.str;}
friend std::ostream& operator<<(std::ostream& os,const texture& x)
{
return os<<x.str;
}
friend std::istream& operator>>(std::istream& is,texture& x)
{
return is>>x.str;
}
std::string str;
};
struct from_texture_to_string
{
const std::string& operator()(const texture& x)const{return x.str;}
};
struct factorization:private boost::noncopyable
{
factorization(int n=0):n(n){}
friend bool operator==(
const factorization& x,const factorization& y){return x.n==y.n;}
friend bool operator< (
const factorization& x,const factorization& y){return x.n< y.n;}
friend bool operator!=(
const factorization& x,const factorization& y){return x.n!=y.n;}
friend bool operator> (
const factorization& x,const factorization& y){return x.n> y.n;}
friend bool operator>=(
const factorization& x,const factorization& y){return x.n>=y.n;}
friend bool operator<=(
const factorization& x,const factorization& y){return x.n<=y.n;}
friend std::ostream& operator<<(std::ostream& os,const factorization& x)
{
return os<<x.n;
}
friend std::istream& operator>>(std::istream& is,factorization& x)
{
return is>>x.n;
}
int n;
};
#endif

View File

@@ -0,0 +1,17 @@
/* Boost.Flyweight test of intermodule_holder.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include "intermod_holder_dll.hpp"
intermodule_flyweight_string create_intermodule_flyweight_string(
const std::string& str)
{
return intermodule_flyweight_string(str);
}

View File

@@ -0,0 +1,45 @@
/* Boost.Flyweight test of intermodule_holder.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_TEST_INTERMOD_HOLDER_DLL_HPP
#define BOOST_FLYWEIGHT_TEST_INTERMOD_HOLDER_DLL_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/flyweight.hpp>
#include <boost/flyweight/hashed_factory.hpp>
#include <boost/flyweight/intermodule_holder.hpp>
#include <boost/flyweight/refcounted.hpp>
#include <boost/flyweight/simple_locking.hpp>
#include <string>
#ifdef BOOST_HAS_DECLSPEC
#ifdef BOOST_FLYWEIGHT_TEST_INTERMOD_HOLDER_DLL_SOURCE
#define BOOST_FLYWEIGHT_DLL_DECL __declspec(dllexport)
#else
#define BOOST_FLYWEIGHT_DLL_DECL __declspec(dllimport)
#endif
#else
#define BOOST_FLYWEIGHT_DLL_DECL
#endif
typedef boost::flyweights::flyweight<
std::string,
boost::flyweights::intermodule_holder> intermodule_flyweight_string;
BOOST_FLYWEIGHT_DLL_DECL intermodule_flyweight_string
create_intermodule_flyweight_string(const std::string&);
#undef BOOST_FLYWEIGHT_DLL_DECL
#endif

36
test/test_all_main.cpp Normal file
View File

@@ -0,0 +1,36 @@
/* Boost.Flyweight test suite.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/lightweight_test.hpp>
#include "test_assoc_cont_factory.hpp"
#include "test_basic.hpp"
#include "test_custom_factory.hpp"
#include "test_intermod_holder.hpp"
#include "test_init.hpp"
#include "test_multictor.hpp"
#include "test_no_locking.hpp"
#include "test_no_tracking.hpp"
#include "test_set_factory.hpp"
int main()
{
test_assoc_container_factory();
test_basic();
test_custom_factory();
test_init();
test_intermodule_holder();
test_multictor();
test_no_locking();
test_no_tracking();
test_set_factory();
return boost::report_errors();
}

View File

@@ -0,0 +1,18 @@
/* Boost.Flyweight test of assoc_container_factory.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/detail/lightweight_test.hpp>
#include "test_assoc_cont_factory.hpp"
int main()
{
test_assoc_container_factory();
return boost::report_errors();
}

View File

@@ -0,0 +1,68 @@
/* Boost.Flyweight test of assoc_container_factory.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include "test_assoc_cont_factory.hpp"
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/assoc_container_factory.hpp>
#include <boost/flyweight/flyweight.hpp>
#include <boost/flyweight/refcounted.hpp>
#include <boost/flyweight/simple_locking.hpp>
#include <boost/flyweight/static_holder.hpp>
#include <functional>
#include <set>
#include "test_basic_template.hpp"
using namespace boost::flyweights;
struct reverse_set_specifier
{
template<typename Entry,typename Key>
struct apply
{
typedef std::set<Entry,std::greater<Key> > type;
};
};
struct assoc_container_factory_flyweight_specifier1
{
template<typename T>
struct apply
{
typedef flyweight<
T,
assoc_container_factory<reverse_set_specifier>
> type;
};
};
struct assoc_container_factory_flyweight_specifier2
{
template<typename T>
struct apply
{
typedef flyweight<
T,
assoc_container_factory_class<
std::set<
boost::mpl::_1,
std::greater<boost::mpl::_2>,
std::allocator<boost::mpl::_1>
>
>
> type;
};
};
void test_assoc_container_factory()
{
test_basic_template<assoc_container_factory_flyweight_specifier1>();
test_basic_template<assoc_container_factory_flyweight_specifier2>();
}

View File

@@ -0,0 +1,11 @@
/* Boost.Flyweight test of assoc_container_factory.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
void test_assoc_container_factory();

68
test/test_basic.cpp Normal file
View File

@@ -0,0 +1,68 @@
/* Boost.Flyweight basic test.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include "test_basic.hpp"
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight.hpp>
#include "test_basic_template.hpp"
using namespace boost::flyweights;
struct basic_flyweight_specifier1
{
template<typename T>
struct apply
{
typedef flyweight<T> type;
};
};
struct basic_flyweight_specifier2
{
template<typename T>
struct apply
{
typedef flyweight<
T,tag<int>,
static_holder_class<boost::mpl::_1>,
hashed_factory_class<
boost::mpl::_1,boost::mpl::_2,
boost::hash<boost::mpl::_2>,std::equal_to<boost::mpl::_2>,
std::allocator<boost::mpl::_1>
>,
simple_locking,
refcounted
> type;
};
};
struct basic_flyweight_specifier3
{
template<typename T>
struct apply
{
typedef flyweight<
T,
hashed_factory<
boost::hash<boost::mpl::_2>,std::equal_to<boost::mpl::_2>,
std::allocator<boost::mpl::_1>
>,
tag<int>
> type;
};
};
void test_basic()
{
test_basic_template<basic_flyweight_specifier1>();
test_basic_template<basic_flyweight_specifier2>();
test_basic_template<basic_flyweight_specifier3>();
}

11
test/test_basic.hpp Normal file
View File

@@ -0,0 +1,11 @@
/* Boost.Flyweight basic test.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
void test_basic();

18
test/test_basic_main.cpp Normal file
View File

@@ -0,0 +1,18 @@
/* Boost.Flyweight basic test.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/detail/lightweight_test.hpp>
#include "test_basic.hpp"
int main()
{
test_basic();
return boost::report_errors();
}

View File

@@ -0,0 +1,232 @@
/* Boost.Flyweight basic test template.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_TEST_BASIC_TEMPLATE_HPP
#define BOOST_FLYWEIGHT_TEST_BASIC_TEMPLATE_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/lightweight_test.hpp>
#include <boost/flyweight/key_value.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/utility/value_init.hpp>
#include <string>
#include <sstream>
#include "heavy_objects.hpp"
#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
template<typename Flyweight,typename ForwardIterator>
void test_basic_template(
ForwardIterator first,ForwardIterator last
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight))
{
typedef typename Flyweight::value_type value_type;
ForwardIterator it;
for(it=first;it!=last;++it){
/* construct/copy/destroy */
Flyweight f1(*it);
Flyweight f2;
Flyweight c1(f1);
Flyweight c2(static_cast<const Flyweight&>(f2));
value_type v1(*it);
boost::value_initialized<value_type> v2;
BOOST_TEST(f1.get_key()==*it);
BOOST_TEST((f1==f2)==(f1.get()==v2.data()));
BOOST_TEST(f1==c1);
BOOST_TEST(f2==c2);
f1=f1;
BOOST_TEST(f1==f1);
c1=f2;
BOOST_TEST(c1==f2);
c1=f1;
BOOST_TEST(c1==f1);
/* convertibility to underlying type */
BOOST_TEST(f1.get()==v1);
/* identity of reference */
BOOST_TEST(&f1.get()==&c1.get());
/* modifiers */
f1.swap(f1);
BOOST_TEST(f1==c1);
f1.swap(f2);
BOOST_TEST(f1==c2);
BOOST_TEST(f2==c1);
boost::flyweights::swap(f1,f2);
BOOST_TEST(f1==c1);
BOOST_TEST(f2==c2);
/* specialized algorithms */
std::ostringstream oss1;
oss1<<f1;
std::ostringstream oss2;
oss2<<f1.get();
BOOST_TEST(oss1.str()==oss2.str());
}
}
template<typename Flyweight,typename ForwardIterator>
void test_basic_with_assign_template(
ForwardIterator first,ForwardIterator last
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight))
{
typedef typename Flyweight::value_type value_type;
ForwardIterator it;
test_basic_template<Flyweight>(first,last);
for(it=first;it!=last;++it){
/* value construction */
value_type v(*it);
Flyweight f1(v);
Flyweight f2(f1.get());
BOOST_TEST(f1.get()==v);
BOOST_TEST(f2.get()==v);
BOOST_TEST(f1==f2);
/* value assignment */
Flyweight f3,f4;
f3=v;
f4=f1.get();
BOOST_TEST(f2.get()==v);
BOOST_TEST(f3.get()==v);
BOOST_TEST(f2==f3);
/* specialized algorithms */
std::ostringstream oss1;
oss1<<f1;
std::istringstream iss1(oss1.str());
Flyweight f5;
iss1>>f5;
BOOST_TEST(f5==f1);
}
}
template<
typename Flyweight1,typename Flyweight2,
typename ForwardIterator1,typename ForwardIterator2
>
void test_basic_comparison_template(
ForwardIterator1 first1,ForwardIterator1 last1,
ForwardIterator2 first2
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight1)
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight2))
{
typedef typename Flyweight1::value_type value_type1;
typedef typename Flyweight2::value_type value_type2;
for(;first1!=last1;++first1,++first2){
value_type1 v1=value_type1(*first1);
value_type2 v2=value_type2(*first2);
Flyweight1 f1(v1);
Flyweight2 f2(v2);
BOOST_TEST((f1==f2)==(f1.get()==v2));
BOOST_TEST((f1< f2)==(f1.get()< v2));
BOOST_TEST((f1!=f2)==(f1.get()!=v2));
BOOST_TEST((f1> f2)==(f1.get()> v2));
BOOST_TEST((f1>=f2)==(f1.get()>=v2));
BOOST_TEST((f1<=f2)==(f1.get()<=v2));
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
BOOST_TEST((f1==v2)==(f1.get()==v2));
BOOST_TEST((f1< v2)==(f1.get()< v2));
BOOST_TEST((f1!=v2)==(f1.get()!=v2));
BOOST_TEST((f1> v2)==(f1.get()> v2));
BOOST_TEST((f1>=v2)==(f1.get()>=v2));
BOOST_TEST((f1<=v2)==(f1.get()<=v2));
BOOST_TEST((v1==f2)==(f1.get()==v2));
BOOST_TEST((v1< f2)==(f1.get()< v2));
BOOST_TEST((v1!=f2)==(f1.get()!=v2));
BOOST_TEST((v1> f2)==(f1.get()> v2));
BOOST_TEST((v1>=f2)==(f1.get()>=v2));
BOOST_TEST((v1<=f2)==(f1.get()<=v2));
#endif
}
}
template<typename FlyweightSpecifier>
void test_basic_template(BOOST_EXPLICIT_TEMPLATE_TYPE(FlyweightSpecifier))
{
typedef typename boost::mpl::apply1<
FlyweightSpecifier,int
>::type int_flyweight;
typedef typename boost::mpl::apply1<
FlyweightSpecifier,std::string
>::type string_flyweight;
typedef typename boost::mpl::apply1<
FlyweightSpecifier,char
>::type char_flyweight;
typedef typename boost::mpl::apply1<
FlyweightSpecifier,
boost::flyweights::key_value<std::string,texture,from_texture_to_string>
>::type texture_flyweight;
typedef typename boost::mpl::apply1<
FlyweightSpecifier,
boost::flyweights::key_value<int,factorization>
>::type factorization_flyweight;
int ints[]={0,1,1,0,1,2,3,4,3,4,0,0};
test_basic_with_assign_template<int_flyweight>(
&ints[0],&ints[0]+LENGTHOF(ints));
const char* words[]={"hello","boost","flyweight","boost","bye","c++","c++"};
test_basic_with_assign_template<string_flyweight>(
&words[0],&words[0]+LENGTHOF(words));
const char* textures[]={"wood","grass","sand","granite","terracotta"};
test_basic_with_assign_template<texture_flyweight>(
&textures[0],&textures[0]+LENGTHOF(textures));
int factorizations[]={1098,102387,90846,2223978};
test_basic_template<factorization_flyweight>(
&factorizations[0],&factorizations[0]+LENGTHOF(factorizations));
char chars[]={0,2,4,5,1,1,1,3,4,1,1,0};
test_basic_comparison_template<int_flyweight,char_flyweight>(
&ints[0],&ints[0]+LENGTHOF(ints),&chars[0]);
test_basic_comparison_template<string_flyweight,string_flyweight>(
&words[0],&words[0]+LENGTHOF(words)-1,&words[1]);
test_basic_comparison_template<texture_flyweight,texture_flyweight>(
&textures[0],&textures[0]+LENGTHOF(textures)-1,&textures[1]);
}
#undef LENGTHOF
#endif

View File

@@ -0,0 +1,111 @@
/* Boost.Flyweight test of a custom factory.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include "test_custom_factory.hpp"
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/flyweight.hpp>
#include <boost/flyweight/refcounted.hpp>
#include <boost/flyweight/simple_locking.hpp>
#include <boost/flyweight/static_holder.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
#include <list>
#include "test_basic_template.hpp"
using namespace boost::flyweights;
/* Info on list-update containers:
* http://gcc.gnu.org/onlinedocs/libstdc++/ext/pb_ds/lu_based_containers.html
*/
template<typename Entry,typename Key>
class lu_factory_class:public factory_marker
{
struct entry_type
{
entry_type(const Entry& x_):x(x_),count(0){}
Entry x;
std::size_t count;
};
typedef std::list<entry_type> container_type;
public:
typedef typename container_type::iterator handle_type;
handle_type insert(const Entry& x)
{
handle_type h;
for(h=cont.begin();h!=cont.end();++h){
if(static_cast<const Key&>(h->x)==static_cast<const Key&>(x)){
if(++(h->count)==10){
h->count=0;
cont.splice(cont.begin(),cont,h); /* move to front */
}
return h;
}
}
cont.push_back(entry_type(x));
h=cont.end();
--h;
return h;
}
void erase(handle_type h)
{
cont.erase(h);
}
const Entry& entry(handle_type h){return h->x;}
private:
container_type cont;
public:
typedef lu_factory_class type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(2,lu_factory_class,(Entry,Key))
};
struct lu_factory:factory_marker
{
template<typename Entry,typename Key>
struct apply
{
typedef lu_factory_class<Entry,Key> type;
};
};
struct custom_factory_flyweight_specifier1
{
template<typename T>
struct apply
{
typedef flyweight<T,lu_factory> type;
};
};
struct custom_factory_flyweight_specifier2
{
template<typename T>
struct apply
{
typedef flyweight<
T,
lu_factory_class<boost::mpl::_1,boost::mpl::_2>
> type;
};
};
void test_custom_factory()
{
test_basic_template<custom_factory_flyweight_specifier1>();
test_basic_template<custom_factory_flyweight_specifier2>();
}

View File

@@ -0,0 +1,11 @@
/* Boost.Flyweight test of a custom factory.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
void test_custom_factory();

View File

@@ -0,0 +1,18 @@
/* Boost.Flyweight test of a custom factory.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/detail/lightweight_test.hpp>
#include "test_custom_factory.hpp"
int main()
{
test_custom_factory();
return boost::report_errors();
}

47
test/test_init.cpp Normal file
View File

@@ -0,0 +1,47 @@
/* Boost.Flyweight test of static data initialization facilities.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include "test_init.hpp"
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/lightweight_test.hpp>
#include <boost/flyweight.hpp>
using namespace boost::flyweights;
template<bool* pmark,typename Entry,typename Value>
struct marked_hashed_factory_class:hashed_factory_class<Entry,Value>
{
marked_hashed_factory_class(){*pmark=true;}
};
template<bool* pmark>
struct marked_hashed_factory:factory_marker
{
template<typename Entry,typename Value>
struct apply
{
typedef marked_hashed_factory_class<pmark,Entry,Value> type;
};
};
namespace{
bool mark1=false;
bool init1=flyweight<int,marked_hashed_factory<&mark1> >::init();
bool mark2=false;
flyweight<int,marked_hashed_factory<&mark2> >::initializer init2;
}
void test_init()
{
BOOST_TEST(mark1);
BOOST_TEST(mark2);
}

11
test/test_init.hpp Normal file
View File

@@ -0,0 +1,11 @@
/* Boost.Flyweight test of static data initialization facilities.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
void test_init();

18
test/test_init_main.cpp Normal file
View File

@@ -0,0 +1,18 @@
/* Boost.Flyweight test of static data initialization facilities.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/detail/lightweight_test.hpp>
#include "test_init.hpp"
int main()
{
test_init();
return boost::report_errors();
}

View File

@@ -0,0 +1,34 @@
/* Boost.Flyweight test of intermodule_holder.
*
* Copyright 2006-2008 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include "test_intermod_holder.hpp"
#include "intermod_holder_dll.hpp"
#include "test_basic_template.hpp"
using namespace boost::flyweights;
struct intermodule_holder_flyweight_specifier1
{
template<typename T>
struct apply
{
typedef flyweight<T,intermodule_holder> type;
};
};
void test_intermodule_holder()
{
test_basic_template<intermodule_holder_flyweight_specifier1>();
intermodule_flyweight_string str=
create_intermodule_flyweight_string("boost");
BOOST_TEST(str==intermodule_flyweight_string("boost"));
}

Some files were not shown because too many files have changed in this diff Show More