diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2013-06-25 22:59:01 +0000 |
---|---|---|
committer | <> | 2013-09-27 11:49:28 +0000 |
commit | 8c4528713d907ee2cfd3bfcbbad272c749867f84 (patch) | |
tree | c09e2ce80f47b90c85cc720f5139089ad9c8cfff /libs/flyweight | |
download | boost-tarball-8c4528713d907ee2cfd3bfcbbad272c749867f84.tar.gz |
Imported from /home/lorry/working-area/delta_boost-tarball/boost_1_54_0.tar.bz2.boost_1_54_0baserock/morph
Diffstat (limited to 'libs/flyweight')
75 files changed, 8616 insertions, 0 deletions
diff --git a/libs/flyweight/doc/acknowledgements.html b/libs/flyweight/doc/acknowledgements.html new file mode 100644 index 000000000..326231853 --- /dev/null +++ b/libs/flyweight/doc/acknowledgements.html @@ -0,0 +1,98 @@ +<!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ñaga, Janek Kozicki, Tobias Schwinger, +Pavel Voženílek. Simon Atanasyan contributed a workaround for a +problem with Sun Studio compilers. Rosa Berná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ñaga, the stalwart review manager, +and to all the reviewers: Alberto Ganesh Barbati, Tim Blechmann, +Vicente Juan Botet Escribá, Matí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ñ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ópez, in the hope that past +dire straits gentler oceans will lie. +</p> + +<h2><a name="boost_1_39">Boost 1.39 release</a></h2> + +<p> +Many thanks to Tim Blechmann for helping identify and solve a serious +<a href="release_notes.html#refcounted_bug">thread safety problem</a> +and to Peter Dimov for kindly extending the interface of his +<code>boost::detail::atomic_count</code> utility to allow for the +implementation of the fix. +</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 April 25th 2009</p> + +<p>© Copyright 2006-2009 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/examples.html b/libs/flyweight/doc/examples.html new file mode 100644 index 000000000..2bef5cf58 --- /dev/null +++ b/libs/flyweight/doc/examples.html @@ -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 <BR>), character +enconding and HTML entities (e.g. "&copy;" for ©) 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<key_value<int,compute_f> ></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><</span><span class=identifier>key_value</span><span class=special><</span><span class=keyword>int</span><span class=special>,</span><span class=identifier>compute_fibonacci</span><span class=special>>,</span><span class=identifier>no_tracking</span><span class=special>></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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/future_work.html b/libs/flyweight/doc/future_work.html new file mode 100644 index 000000000..17e48e5f0 --- /dev/null +++ b/libs/flyweight/doc/future_work.html @@ -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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></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><<</span><span class=string>"factory used: "</span><span class=special><<</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>()<<</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><<</span><span class=string>"values stored: "</span><span class=special><<</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>()<<</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<T> 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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/html.png b/libs/flyweight/doc/html.png Binary files differnew file mode 100644 index 000000000..d06799f33 --- /dev/null +++ b/libs/flyweight/doc/html.png diff --git a/libs/flyweight/doc/index.html b/libs/flyweight/doc/index.html new file mode 100644 index 000000000..ad252b2fe --- /dev/null +++ b/libs/flyweight/doc/index.html @@ -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<T></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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/memory.png b/libs/flyweight/doc/memory.png Binary files differnew file mode 100644 index 000000000..703878d0c --- /dev/null +++ b/libs/flyweight/doc/memory.png diff --git a/libs/flyweight/doc/memory_gcc_344.png b/libs/flyweight/doc/memory_gcc_344.png Binary files differnew file mode 100644 index 000000000..289796e98 --- /dev/null +++ b/libs/flyweight/doc/memory_gcc_344.png diff --git a/libs/flyweight/doc/memory_msvc_80.png b/libs/flyweight/doc/memory_msvc_80.png Binary files differnew file mode 100644 index 000000000..218443781 --- /dev/null +++ b/libs/flyweight/doc/memory_msvc_80.png diff --git a/libs/flyweight/doc/next.gif b/libs/flyweight/doc/next.gif Binary files differnew file mode 100644 index 000000000..d6c18a578 --- /dev/null +++ b/libs/flyweight/doc/next.gif diff --git a/libs/flyweight/doc/performance.html b/libs/flyweight/doc/performance.html new file mode 100644 index 000000000..cac737fa5 --- /dev/null +++ b/libs/flyweight/doc/performance.html @@ -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<T>)=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<T,...></code> +need not only hold a value of <code>T</code>, but also contain additional +information related to the internal implementation of +<code>flyweight<T,...></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"> <a href="tutorial/key_value.html#key_value"><code>key_value</code></a> </td> + <td align="center"> with <a href="tutorial/key_value.html#key_extractor">key extractor</a> </td> + <td align="center"> 1<sup>(1)</sup> </td> +</tr> +<tr> + <td align="center"> without <a href="tutorial/key_value.html#key_extractor">key extractor</a> </td> + <td align="center"> 1 + <code>sizeof(Key) </td> +</tr> +<tr class="odd_tr"> + <td align="center" rowspan="3"> factory </td> + <td align="center"> <a href="tutorial/configuration.html#hashed_factory"><code>hashed_factory</code></a> </td> + <td align="center"> ~2.5 </td> +</tr> +<tr class="odd_tr"> + <td align="center"> <a href="tutorial/configuration.html#set_factory"><code>set_factory</code></a> </td> + <td align="center"> 4<sup>(2)</sup> </td> +</tr> +<tr class="odd_tr"> + <td align="center"> <a href="tutorial/configuration.html#assoc_container_factory"><code>assoc_container_factory</code></a> </td> + <td align="center"> depends on the container used </td> +</tr> +<tr> + <td align="center" rowspan="2"> tracking mechanism </td> + <td align="center"> <a href="tutorial/configuration.html#refcounted"><code>refcounted</code></a> </td> + <td align="center"> 2<sup>(3)</sup> </td> +</tr> +<tr> + <td align="center"> <a href="tutorial/configuration.html#no_tracking"><code>no_tracking</code></a> </td> + <td align="center"> 0 </td> +</tr> +</table> +<sup>(1)</sup> <small>Assuming that <code>sizeof(Key)<=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 3.</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>) + 2(<code>refcounted</code>) += 4.5 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>·<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<T,...></code>, the resulting memory consumption +will be +</p> + +<blockquote> +<i>S<sub>F</sub></i> = +<i>N</i>·<i>P</i> + <i>M</i>·(<i>T</i> + <i>overhead</i>), +</blockquote> + +<p> +where <i>P</i> is <code>sizeof(flyweight<T,...>)</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<T></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<T></code> to <code>const T&</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<T></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<std::string></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<std::string,<a href="tutorial/configuration.html#no_tracking"><code>no_tracking</code></a>></code>.</li> + <li><code>flyweight<std::string,<a href="tutorial/configuration.html#set_factory"><code>set_factory</code></a>></code>.</li> + <li><code>flyweight<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>></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="323"><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="325"><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 20% and 40% +of additional execution time), while the other usage contexts +(assignment, equality comparison and value access) have performance gains, +with speedup factors of more than 10 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="323"><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="325"><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 (×25 +in equality comparison and up to ×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 June 22nd 2009</p> + +<p>© Copyright 2006-2009 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/prev.gif b/libs/flyweight/doc/prev.gif Binary files differnew file mode 100644 index 000000000..c35dfeec2 --- /dev/null +++ b/libs/flyweight/doc/prev.gif diff --git a/libs/flyweight/doc/reference/factories.html b/libs/flyweight/doc/reference/factories.html new file mode 100644 index 000000000..e047b6009 --- /dev/null +++ b/libs/flyweight/doc/reference/factories.html @@ -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&</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&</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<S>::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<S'></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><</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>></span> +<span class=keyword>struct</span> <span class=identifier>is_factory</span><span class=special>;</span> + +<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>></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<T>::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<T></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><</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>></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><</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>></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><</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>></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>&</span> <span class=identifier>x</span><span class=special>);</span> + <span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span> + <span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span> +<span class=special>};</span> +</pre></blockquote> + +<p> +<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<std::size_t>::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<Key></code></a> +and <code>std::equal_to<Key></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<Entry></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><</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>></span> +<span class=keyword>struct</span> <span class=identifier>hashed_factory</span><span class=special>;</span> +</pre></blockquote> + +<p> +<code>hashed_factory<Hash,Pred,Allocator></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><</span> + <span class=identifier>hashed_factory</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>>,</span> + <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span> +<span class=special>>::</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><</span> + <span class=identifier>hashed_factory_class</span><span class=special><</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_2</span><span class=special>,</span><span class=identifier>Hash</span><span class=special>,</span><span class=identifier>Pred</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span> + <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span> +<span class=special>>::</span><span class=identifier>type</span> +</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><</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>></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><</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>></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><</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>></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>&</span> <span class=identifier>x</span><span class=special>);</span> + <span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span> + <span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span> +<span class=special>};</span> +</pre></blockquote> + +<p> +<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)&&!c(y,x)</code> for <code>c</code> of type <code>Compare</code>. +The default argument of <code>Compare</code> is <code>std::less<Key></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<Entry></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><</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>></span> +<span class=keyword>struct</span> <span class=identifier>set_factory</span><span class=special>;</span> +</pre></blockquote> + +<p> +<code>set_factory<Compare,Allocator></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><</span> + <span class=identifier>set_factory</span><span class=special><</span><span class=identifier>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span> + <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span> +<span class=special>>::</span><span class=identifier>type</span> +</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><</span> + <span class=identifier>set_factory_class</span><span class=special><</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_2</span><span class=special>,</span><span class=identifier>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span> + <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span> +<span class=special>>::</span><span class=identifier>type</span> +</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><</span><span class=keyword>typename</span> <span class=identifier>Container</span><span class=special>></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><</span><span class=keyword>typename</span> <span class=identifier>ContainerSpecifier</span><span class=special>></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><</span><span class=keyword>typename</span> <span class=identifier>Container</span><span class=special>></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>&</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>&</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><</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special><</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><</span><span class=identifier>base</span><span class=special>></span> <span class=special>></span> <span class=comment>// derived inherits from base</span> +<span class=special>></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><</span><span class=keyword>typename</span> <span class=identifier>ContainerSpecifier</span><span class=special>></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<Container></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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/reference/flyweight.html b/libs/flyweight/doc/reference/flyweight.html new file mode 100644 index 000000000..e0cf99831 --- /dev/null +++ b/libs/flyweight/doc/reference/flyweight.html @@ -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><</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>></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 ==,<,!=,>,>=,<=</span> + +<span class=keyword>template</span><span class=special><</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>></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><</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>>&</span> <span class=identifier>x</span><span class=special>,</span> + <span class=keyword>const</span> <span class=identifier>flyweight</span><span class=special><</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>>&</span> <span class=identifier>y</span><span class=special>);</span> + +<span class=keyword>template</span><span class=special><</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>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><</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>>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>T2</span><span class=special>&</span> <span class=identifier>y</span><span class=special>);</span> + +<span class=keyword>template</span><span class=special><</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>></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>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>flyweight</span><span class=special><</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>>&</span> <span class=identifier>y</span><span class=special>);</span> + +<span class=comment>// specialized algorithms:</span> + +<span class=keyword>template</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>></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><</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>>&</span> <span class=identifier>x</span><span class=special>,</span><span class=identifier>flyweight</span><span class=special><</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>>&</span> <span class=identifier>y</span><span class=special>);</span> + +<span class=keyword>template</span><span class=special><</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>></span> +<span class=keyword>inline</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>basic_ostream</span><span class=special><</span><span class=identifier>ElemType</span><span class=special>,</span><span class=identifier>Traits</span><span class=special>>&</span> <span class=keyword>operator</span><span class=special><<(</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>basic_ostream</span><span class=special><</span><span class=identifier>ElemType</span><span class=special>,</span><span class=identifier>Traits</span><span class=special>>&</span> <span class=identifier>out</span><span class=special>,</span> + <span class=keyword>const</span> <span class=identifier>flyweight</span><span class=special><</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>>&</span> <span class=identifier>x</span><span class=special>);</span> + +<span class=keyword>template</span><span class=special><</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>></span> +<span class=keyword>inline</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>basic_ostream</span><span class=special><</span><span class=identifier>ElemType</span><span class=special>,</span><span class=identifier>Traits</span><span class=special>>&</span> <span class=keyword>operator</span><span class=special>>>(</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>basic_istream</span><span class=special><</span><span class=identifier>ElemType</span><span class=special>,</span><span class=identifier>Traits</span><span class=special>>&</span> <span class=identifier>in</span><span class=special>,</span> + <span class=identifier>flyweight</span><span class=special><</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>>&</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<...></code> provide access to immutable +values of type <code>flyweight<...>::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&</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><</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>></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>&</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>&</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><</span><span class=keyword>typename</span> <span class=identifier>T0</span><span class=special>></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>&</span> <span class=identifier>t0</span><span class=special>);</span> + <span class=keyword>template</span><span class=special><</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>></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>&</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>&</span> <span class=identifier>t1</span><span class=special>);</span> + <span class=special>...</span> + <span class=keyword>template</span><span class=special><</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>></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>&</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>&</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>&</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <span class=identifier>flyweight</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span> + <span class=identifier>flyweight</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</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>&</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>&</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>&()</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>&</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<Key,Value[,KeyFromValue]></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<></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& x);<br> +flyweight(flyweight& 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<typename T0><br> +explicit flyweight([const] T0& t0);<br> +template<typename T0,typename T1><br> +flyweight([const] T0& t0,[const] T1& t1);<br> +...<br> +template<typename T0,...,typename Tn-1><br> +flyweight([const] T0& t0,...,[const] Tn-1& 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& operator=(const flyweight& 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& operator=(const value_type& 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<></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& 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& get()const;<br> + operator const value_type&()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& 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<<br> + typename T1,typename Arg11,...,typename Arg15,<br> + typename T2,typename Arg21,...,typename Arg25<br> +><br> +bool operator ==(<br> + const flyweight<T1,Arg11,...,Arg15>& x,<br> + const flyweight<T2,Arg21,...,Arg25>& 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<<br> + typename T1,typename Arg11,...,typename Arg15,<br> + typename T2<br> +><br> +bool operator ==(const flyweight<T1,Arg11,...,Arg15>& x,const T2& y);</code> + +<blockquote> +<b>Returns:</b> <code>x.get()==y</code>. +</blockquote> + +<code>template<<br> + typename T1,<br> + typename T2,typename Arg21,...,typename Arg25<br> +><br> +bool operator ==(const T1& x,const flyweight<T2,Arg21,...,Arg25>& y);</code> + +<blockquote> +<b>Returns:</b> <code>x()==y.get()</code>. +</blockquote> + +<code>template<<br> + typename T1,typename Arg11,...,typename Arg15,<br> + typename T2,typename Arg21,...,typename Arg25<br> +><br> +bool operator <(<br> + const flyweight<T1,Arg11,...,Arg15>& x,<br> + const flyweight<T2,Arg21,...,Arg25>& y);</code> + +<blockquote> +<b>Returns:</b> <code>x.get()<y.get()</code>. +</blockquote> + +<code>template<<br> + typename T1,typename Arg11,...,typename Arg15,<br> + typename T2<br> +><br> +bool operator <(const flyweight<T1,Arg11,...,Arg15>& x,const T2& y);</code> + +<blockquote> +<b>Returns:</b> <code>x.get()<y</code>. +</blockquote> + +<code>template<<br> + typename T1,<br> + typename T2,typename Arg21,...,typename Arg25<br> +><br> +bool operator <(const T1& x,const flyweight<T2,Arg21,...,Arg25>& y);</code> + +<blockquote> +<b>Returns:</b> <code>x()<y.get()</code>. +</blockquote> + + +<code>template<<br> + typename T1,typename Arg11,...,typename Arg15,<br> + typename T2,typename Arg21,...,typename Arg25<br> +><br> +bool operator <b><i>OP</i></b>(<br> + const flyweight<T1,Arg11,...,Arg15>& x,<br> + const flyweight<T2,Arg21,...,Arg25>& y);<br> +template<<br> + typename T1,typename Arg11,...,typename Arg15,<br> + typename T2<br> +><br> +bool operator <b><i>OP</i></b>(const flyweight<T1,Arg11,...,Arg15>& x,const T2& y);</br> +template<<br> + typename T1,<br> + typename T2,typename Arg21,...,typename Arg25<br> +><br> +bool operator <b><i>OP</i></b>(const T1& x,const flyweight<T2,Arg21,...,Arg25>& y);</code> + +<p> +(<code><b><i>OP</i></b></code> is any of <code>!=</code>, <code>></code>, +<code>>=</code>, <code><=</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> y< x </code> (<code><b><i>OP</i></b></code> is <code>> </code>),<br> +<code>!(x< y)</code> (<code><b><i>OP</i></b></code> is <code>>=</code>),<br> +<code>!(y< x)</code> (<code><b><i>OP</i></b></code> is <code><=</code>). +</blockquote> +</blockquote> + +<h4><a name="specialized">Specialized algorithms</a></h4> + +<code>template<typename T,typename Arg1,...,typename Arg5><br> +inline void swap(<br> + flyweight<T,Arg1,...,Arg5>& x,flyweight<T,Arg1,...,Arg5>& y);</code> + +<blockquote> +<b>Effects:</b> <code>x.swap(y)</code>. +</blockquote> + +<code>template<<br> + typename ElemType,typename Traits, <br> + typename T,typename Arg1,...,typename Arg5<br> +><br> +inline std::basic_ostream<ElemType,Traits>& operator<<(<br> + std::basic_ostream<ElemType,Traits>& out,<br> + const flyweight<T,Arg1,...,Arg5>& x);</code> + +<blockquote> +<b>Effects:</b> <code>out<<x.get()</code>.<br> +<b>Returns:</b> <code>out</code>. +</blockquote> + +<code>template<<br> + typename ElemType,typename Traits, <br> + typename T,typename Arg1,...,typename Arg5<br> +><br> +inline std::basic_ostream<ElemType,Traits>& operator>>(<br> + std::basic_istream<ElemType,Traits>& in,<br> + flyweight<T,Arg1,...,Arg5>& 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<></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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/reference/holders.html b/libs/flyweight/doc/reference/holders.html new file mode 100644 index 000000000..c8e910dc6 --- /dev/null +++ b/libs/flyweight/doc/reference/holders.html @@ -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<S>::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<S'></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><</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>></span> +<span class=keyword>struct</span> <span class=identifier>is_holder</span><span class=special>;</span> + +<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>></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<T>::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<T></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><</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>></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<C></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><</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>></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<C></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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/reference/index.html b/libs/flyweight/doc/reference/index.html new file mode 100644 index 000000000..1f653824e --- /dev/null +++ b/libs/flyweight/doc/reference/index.html @@ -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="../tutorial/lambda_expressions.html"> +<link rel="up" href="../index.html"> +<link rel="next" href="flyweight.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><</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>></span> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>hashed_factory</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>refcounted</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>simple_locking</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>static_holder</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></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 January 27th 2009</p> + +<p>© Copyright 2006-2009 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/reference/key_value.html b/libs/flyweight/doc/reference/key_value.html new file mode 100644 index 000000000..d1d0364e1 --- /dev/null +++ b/libs/flyweight/doc/reference/key_value.html @@ -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&</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><</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>></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<T,...></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<key_value<Key,Value[,KeyFromValue]>,...></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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/reference/locking.html b/libs/flyweight/doc/reference/locking.html new file mode 100644 index 000000000..64ed82e49 --- /dev/null +++ b/libs/flyweight/doc/reference/locking.html @@ -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> </td> + <td>Post: <code>m</code> is unlocked. + </td> +</tr> +<tr class="odd_tr"> + <td><code>(&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> </td> + <td>Associates <code>m</code> to <code>lk</code> and locks <code>m</code>.</td> +</tr> +<tr class="odd_tr"> + <td><code>(&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/synchronization.html#thread.synchronization.mutex_concepts">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<Locking>::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="#locking_construct"><code>locking<Locking'></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><</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>></span> +<span class=keyword>struct</span> <span class=identifier>is_locking</span> + +<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>></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<T>::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<T></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 March 9th 2010</p> + +<p>© Copyright 2006-2010 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/reference/tags.html b/libs/flyweight/doc/reference/tags.html new file mode 100644 index 000000000..c58ab8622 --- /dev/null +++ b/libs/flyweight/doc/reference/tags.html @@ -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<T></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><</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>></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<T></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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/reference/tracking.html b/libs/flyweight/doc/reference/tracking.html new file mode 100644 index 000000000..b310bfcd8 --- /dev/null +++ b/libs/flyweight/doc/reference/tracking.html @@ -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&</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<Tracking>::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<Tracking'></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&</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&</code> + and <code>const Key&</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><</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>></span> +<span class=keyword>struct</span> <span class=identifier>is_tracking</span> + +<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>></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<T>::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<T></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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/release_notes.html b/libs/flyweight/doc/release_notes.html new file mode 100644 index 000000000..b02441205 --- /dev/null +++ b/libs/flyweight/doc/release_notes.html @@ -0,0 +1,118 @@ +<!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_45">Boost 1.45 release</a></li> + <li><a href="#boost_1_44">Boost 1.44 release</a></li> + <li><a href="#boost_1_40">Boost 1.40 release</a></li> + <li><a href="#boost_1_39">Boost 1.39 release</a></li> + <li><a href="#boost_1_38">Boost 1.38 release</a></li> +</ul> + +<h2><a name="boost_1_45">Boost 1.45 release</a></h2> + +<p> +<ul> + <li>Fixed a hanging problem with + <a href="tutorial/configuration.html#intermodule_holder"><code>intermodule_holder</code></a> + in Win32 platforms related to a Boost.Interprocess issue described at + ticket <a href="https://svn.boost.org/trac/boost/ticket/4606">#4606</a>. + </li> + <li>Removed an internal assertion incompatible with program termination + via <code>std::exit</code>. + </li> +</ul> +</p> + +<h2><a name="boost_1_44">Boost 1.44 release</a></h2> + +<p> +<ul> + <li>Fixed an incorrect mode of usage of Boost.Variant in + <a href="examples.html#example3">one of the examples</a>. + </li> +</ul> +</p> + +<h2><a name="boost_1_40">Boost 1.40 release</a></h2> + +<p> +<ul> + <li>Maintenance fixes.</li> +</ul> +</p> + +<h2><a name="boost_1_39">Boost 1.39 release</a></h2> + +<p> +<ul> + <li><a name="refcounted_bug">The <a href="tutorial/configuration.html#refcounted"><code>refcounted</code></a> + component was not thread-safe due to an incorrect implementation and could deadlock + under heavy usage conditions. This problem has been corrected.</a> + </li> +</ul> +</p> + +<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 October 16th 2010</p> + +<p>© Copyright 2006-2010 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/style.css b/libs/flyweight/doc/style.css new file mode 100644 index 000000000..99e7da3a0 --- /dev/null +++ b/libs/flyweight/doc/style.css @@ -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;} diff --git a/libs/flyweight/doc/tests.html b/libs/flyweight/doc/tests.html new file mode 100644 index 000000000..3da7f2296 --- /dev/null +++ b/libs/flyweight/doc/tests.html @@ -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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/time_gcc_344.png b/libs/flyweight/doc/time_gcc_344.png Binary files differnew file mode 100644 index 000000000..c778a7615 --- /dev/null +++ b/libs/flyweight/doc/time_gcc_344.png diff --git a/libs/flyweight/doc/time_msvc_80.png b/libs/flyweight/doc/time_msvc_80.png Binary files differnew file mode 100644 index 000000000..56d97933e --- /dev/null +++ b/libs/flyweight/doc/time_msvc_80.png diff --git a/libs/flyweight/doc/tutorial/basics.html b/libs/flyweight/doc/tutorial/basics.html new file mode 100644 index 000000000..2af60575d --- /dev/null +++ b/libs/flyweight/doc/tutorial/basics.html @@ -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><</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>></span> + +<span class=keyword>struct</span> <span class=identifier>user_entry</span> +<span class=special>{</span> + <span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=identifier>first_name</span><span class=special>;</span> + <span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=identifier>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<std::string></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<T> 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>&</span> <span class=identifier>user1</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&</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>&&</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<T> provides operator<< and operator>> internally +// forwarding to T::operator<< and T::operator>></span> + +<span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream</span><span class=special>&</span> <span class=keyword>operator</span><span class=special><<(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream</span><span class=special>&</span> <span class=identifier>os</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&</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><<</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special><<</span><span class=string>" "</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=string>" "</span><span class=special><<</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>&</span> <span class=keyword>operator</span><span class=special>>>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>istream</span><span class=special>&</span> <span class=identifier>is</span><span class=special>,</span><span class=identifier>user_entry</span><span class=special>&</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>>></span><span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</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>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<T></code> is convertible to +<code>const T&</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>&</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&</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>" "</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>&</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>&</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>&</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<T></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<T></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<T></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<T></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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/tutorial/configuration.html b/libs/flyweight/doc/tutorial/configuration.html new file mode 100644 index 000000000..f8a53a38b --- /dev/null +++ b/libs/flyweight/doc/tutorial/configuration.html @@ -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><</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><</span><span class=identifier>label_t</span><span class=special>>,</span> <span class=identifier>set_factory</span><span class=special><>,</span> <span class=identifier>no_tracking</span> <span class=special>></span> +</pre></blockquote> + +<p> +or like this: +</p> + +<blockquote><pre> +<span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span> <span class=identifier>no_tracking</span><span class=special>,</span> <span class=identifier>tag</span><span class=special><</span><span class=identifier>label_t</span><span class=special>>,</span> <span class=identifier>set_factory</span><span class=special><></span> <span class=special>></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><</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>></span> <span class=comment>// class template flyweight</span> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>hashed_factory</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> <span class=comment>// hashed flyweight factory</span> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>static_holder</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> <span class=comment>// regular factory instantiation</span> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>simple_locking</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> <span class=comment>// simple locking policy</span> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>refcounted</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=identifier>name_t</span><span class=special>;</span> +<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=identifier>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><</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><</span><span class=identifier>name_tag</span><span class=special>></span> <span class=special>></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><</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><</span><span class=identifier>ip_address_tag</span><span class=special>></span> <span class=special>></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<T></code> is +actually equivalent to +</p> + +<blockquote><pre> +<span class=identifier>flyweight</span><span class=special><</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>hashed_factory</span><span class=special><></span> <span class=special>></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&</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<[Hash[,Pred[,Allocator]]]></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><</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>hashed_factory</span><span class=special><></span> <span class=special>></span> +</pre></blockquote> + +<p> +is equivalent to +</p> + +<blockquote><pre> +<span class=identifier>flyweight</span><span class=special><</span> + <span class=identifier>T</span><span class=special>,</span> + <span class=identifier>hashed_factory</span><span class=special><</span> + <span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special><</span><span class=identifier>key_value</span><span class=special>>,</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special><</span><span class=identifier>key_value</span><span class=special>>,</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special><</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>></span> + <span class=special>></span> +<span class=special>></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><</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><</span> + <span class=identifier>special_hash</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>,</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special><</span><span class=identifier>key_value</span><span class=special>>,</span> + <span class=identifier>custom_allocator</span><span class=special><</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>></span> + <span class=special>></span> +<span class=special>></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<[Compare[,Allocator]]></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><</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>set_factory</span><span class=special><></span> <span class=special>></span> +</pre></blockquote> + +<p> +is equivalent to +</p> + +<blockquote><pre> +<span class=identifier>flyweight</span><span class=special><</span> + <span class=identifier>T</span><span class=special>,</span> + <span class=identifier>set_factory</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special><</span><span class=identifier>key_type</span><span class=special>>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special><</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>></span> <span class=special>></span> +<span class=special>></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<ContainerSpecifier></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><</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><</span><span class=identifier>Elem</span><span class=special>>,</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><</span><span class=identifier>Elem</span><span class=special>></span> +<span class=special>></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><</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><</span> + <span class=comment>// MPL lambda expression follows</span> + <b><span class=identifier>ultrafast_set</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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=special>></span></b> + <span class=special>></span> +<span class=special>></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&</code> +(here <code>const std::string&</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><</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><</span> + <b><span class=identifier>ultrafast_set</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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>,</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</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=special>></span> + <span class=special>></span></b> +<span class=special>></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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></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>"boost"</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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></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>"boost"</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><</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>></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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/tutorial/extension.html b/libs/flyweight/doc/tutorial/extension.html new file mode 100644 index 000000000..b82967309 --- /dev/null +++ b/libs/flyweight/doc/tutorial/extension.html @@ -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><</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>></span> +<span class=keyword>class</span> <span class=identifier>custom_factory_class</span> +<span class=special>{</span> +<span class=keyword>public</span><span class=special>:</span> + <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>handle_type</span><span class=special>;</span> + + <span class=identifier>handle_type</span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span> + <span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span> + <span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span> +<span class=special>};</span> +</pre></blockquote> + +<p> +Factories are parameterized by <code>Entry</code> and <code>Key</code>: +the first is the type of the objects stored, while the second is the public +key type on which <code>flyweight</code> operates (e.g. the <code>std::string</code> +in <code>flyweight<std::string></code> or +<code>flyweight<key_value<std::string,texture> ></code>). An entry holds a +shared value to which flyweight objects are associated as well as internal bookkeeping information, but from the +point of view of the factory, though, the only fact known about <code>Entry</code> +is that it is implicitly convertible to <code>const Key&</code>, and it is +based on their associated <code>Key</code> that entries are to be considered +equivalent or not. The factory <code>insert()</code> +member function locates a previously stored entry whose +associated <code>Key</code> is equivalent to that of the <code>Entry</code> +object being passed (for some equivalence relation on <code>Key</code> germane to +the factory), or stores the new entry if no equivalent one is found. A +<code>handle_type</code> to the equivalent or newly inserted entry is returned; +this <code>handle_type</code> is a token for further access to an entry via +<code>erase()</code> and <code>entry()</code>. Consult the +<a href="../reference/factories.html#factory">reference</a> for the formal +definition of the <code>Factory</code> concept. +</p> + +<p> +Let us see an actual example of realization of a custom factory class. Suppose +we want to trace the different invocations by Boost.Flyweight of the +<code>insert()</code> and <code>erase()</code> member functions: this can be +done by using a custom factory whose member methods emit trace messages +to the program console. We base the implementation of the repository +functionality on a regular <code>std::set</code>: + +<blockquote><pre> +<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>></span> +<span class=keyword>class</span> <span class=identifier>verbose_factory_class</span> +<span class=special>{</span> + <span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special><</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special><</span><span class=identifier>Key</span><span class=special>></span> <span class=special>></span> <span class=identifier>store_type</span><span class=special>;</span> + + <span class=identifier>store_type</span> <span class=identifier>store</span><span class=special>;</span> + +<span class=keyword>public</span><span class=special>:</span> + <span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>store_type</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>handle_type</span><span class=special>;</span> + + <span class=identifier>handle_type</span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span> + <span class=special>{</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>handle_type</span><span class=special>,</span> <span class=keyword>bool</span><span class=special>></span> <span class=identifier>p</span><span class=special>=</span><span class=identifier>store</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>x</span><span class=special>);</span> + <span class=keyword>if</span><span class=special>(</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>second</span><span class=special>){</span> <span class=comment>/* new entry */</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special><<</span><span class=string>"new: "</span><span class=special><<(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&)</span><span class=identifier>x</span><span class=special><<</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span> + <span class=special>}</span> + <span class=keyword>else</span><span class=special>{</span> <span class=comment>/* existing entry */</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special><<</span><span class=string>"hit: "</span><span class=special><<(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&)</span><span class=identifier>x</span><span class=special><<</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span> + <span class=special>}</span> + <span class=keyword>return</span> <span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>;</span> + <span class=special>}</span> + + <span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>)</span> + <span class=special>{</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special><<</span><span class=string>"del: "</span><span class=special><<(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&)*</span><span class=identifier>h</span><span class=special><<</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span> + <span class=identifier>store</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>h</span><span class=special>);</span> + <span class=special>}</span> + + <span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>)</span> + <span class=special>{</span> + <span class=keyword>return</span> <span class=special>*</span><span class=identifier>h</span><span class=special>;</span> + <span class=special>}</span> +<span class=special>};</span> +</pre></blockquote> + +<p> +The code deserves some commentaries: +<ul> + <li> + Note that the factory is parameterized by <code>Entry</code> + and <code>Key</code>, as these types are provided internally by Boost.Flyweight + when the factory is instantiated as part of the machinery of <code>flyeight</code>; + but there is nothing to prevent us from having more template parameters for + finer configuration of the factory type: for instance, we could extend + <code>verbose_factory_class</code> to accept some comparison predicate rather than + the default <code>std::less<Key></code>, or to specify the allocator + used by the internal <code>std::set</code>. + </li> + <li> + The fact that <code>Entry</code> is convertible to <code>const Key&</code> + (which is about the only property known about <code>Entry</code>) is + exploited in the specification of <code>std::less<Key></code> as + the comparison predicate for the <code>std::set</code> of <code>Entry</code>s + used as the internal repository. + </li> + <li> + As our public <code>handle_type</code> we are simply using an iterator to the + internal <code>std::set</code>. + </li> +</ul> +</p> + +<p> +In order to plug a custom factory into the specification of a <code>flyweight</code> +type, we need an associated construct called the <i>factory specifier</i>. +A factory specifier is a +<a href="lambda_expressions.html"><code>Lambda +Expression</code></a> accepting the two argument types <code>Entry</code> +and <code>Key</code> and returning the corresponding factory class: +</p> + +<blockquote><pre> +<span class=comment>// Factory specifier (metafunction class version)</span> + +<span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span> +<span class=special>{</span> + <span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> + <span class=keyword>struct</span> <span class=identifier>apply</span> + <span class=special>{</span> + <span class=keyword>typedef</span> <span class=identifier>custom_factory_class</span><span class=special><</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> <span class=identifier>type</span><span class=special>;</span> + <span class=special>}</span> +<span class=special>};</span> + +<span class=comment>// Factory specifier (placeholder version)</span> + +<span class=keyword>typedef</span> <span class=identifier>custom_factory_class</span><span class=special><</span> + <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</span> + <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_2</span> +<span class=special>></span> <span class=identifier>custom_factory_specifier</span><span class=special>;</span> +</pre></blockquote> + +<p> +There is one last detail: in order to implement <code>flyweight</code> +<a href="configuration.html#free_order_template">free-order template +parameter interface</a>, it is necessary to explicitly tag a +factory specifier as such, so that it can be distinguised from other +types of specifiers. Boost.Flyweight provides three different mechanisms +to do this tagging: +<ol> + <li>Have the specifier derive from the dummy type <code>factory_marker</code>. + Note that this mechanism cannot be used with placeholder expressions. +<blockquote><pre> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> + +<span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span><span class=special>:</span> <span class=identifier><b>factory_marker</b></span> +<span class=special>{</span> + <span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> + <span class=keyword>struct</span> <span class=identifier>apply</span> + <span class=special>{</span> + <span class=keyword>typedef</span> <span class=identifier>custom_factory_class</span><span class=special><</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> <span class=identifier>type</span><span class=special>;</span> + <span class=special>}</span> +<span class=special>};</span> +</pre></blockquote> + </li> + <li>Specialize a special class template called + <a href="../reference/factories.html#is_factory"><code>is_factory</code></a>: +<blockquote><pre> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> + +<span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span><span class=special>{};</span> + +<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> +<span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> + +<span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_factory</span><span class=special><</span><span class=identifier>custom_factory_specifier</span><span class=special>>:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span> + +<span class=special>}</span> +<span class=special>}</span> +</pre></blockquote> + </li> + <li>The third mechanism, which is the least intrusive, consists in + wrapping the specifier inside the + <a href="../reference/factories.html#factory_construct"><code>factory</code></a> + construct: +<blockquote><pre> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> + +<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special><</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span> + <span class=identifier><b>factory</b></span><span class=special><</span><span class=identifier>custom_factory_specifier</span><span class=special>></span> +<span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> +</pre></blockquote> + </li> +</ol> +</p> + +<p> +<a href="../examples.html#example7">Example 7</a> in the examples section develops +in full the <code>verbose_factory_class</code> case sketched above. +</p> + +<h2><a name="holders">Custom holders</a></h2> + +<p> +A holder is a class with a static member function <code>get()</code> giving +access to a unique instance of a given type <code>C</code>: +</p> + +<blockquote><pre> +<span class=comment>// example of a possible holder class template</span> + +<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>></span> +<span class=keyword>class</span> <span class=identifier>custom_holder_class</span> +<span class=special>{</span> +<span class=keyword>public</span><span class=special>:</span> + <span class=keyword>static</span> <span class=identifier>C</span><span class=special>&</span> <span class=identifier>get</span><span class=special>();</span> +<span class=special>};</span> +</pre></blockquote> + +<p> +<code>flyweight</code> internally uses a holder to create its associated +factory as well as some other global data. A holder specifier is a +<a href="lambda_expressions.html"><code>Lambda +Expression</code></a> accepting the type <code>C</code> upon which +the associated holder class operates: +</p> + +<blockquote><pre> +<span class=comment>// Holder specifier (metafunction class version)</span> + +<span class=keyword>struct</span> <span class=identifier>custom_holder_specifier</span> +<span class=special>{</span> + <span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>></span> + <span class=keyword>struct</span> <span class=identifier>apply</span> + <span class=special>{</span> + <span class=keyword>typedef</span> <span class=identifier>custom_holder_class</span><span class=special><</span><span class=identifier>C</span><span class=special>></span> <span class=identifier>type</span><span class=special>;</span> + <span class=special>}</span> +<span class=special>};</span> + +<span class=comment>// Holder specifier (placeholder version)</span> + +<span class=keyword>typedef</span> <span class=identifier>custom_holder_class</span><span class=special><</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>></span> <span class=identifier>custom_factory_specifier</span><span class=special>;</span> +</pre></blockquote> + +<p> +As is the case with <a href="#factories">factory specifiers</a>, holder +specifiers must be tagged in order to be properly recognized when +provided to <code>flyweight</code>, and there are three available mechanisms +to do so: +</p> + +<blockquote><pre> +<span class=comment>// Alternatives for tagging a holder specifier</span> + +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>holder_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> + +<span class=comment>// 1: Have the specifier derive from holder_marker</span> + +<span class=keyword>struct</span> <span class=identifier>custom_holder_specifier</span><span class=special>:</span> <span class=identifier><b>holder_marker</b></span> +<span class=special>{</span> + <span class=special>...</span> +<span class=special>};</span> + +<span class=comment>// 2: Specialize the is_holder class template</span> + +<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> +<span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> + +<span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_holder</span><span class=special><</span><span class=identifier>custom_holder_specifier</span><span class=special>>:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span> + +<span class=special>}}</span> + +<span class=comment>// 3: use the holder<> wrapper when passing the specifier +// to flyweight</span> + +<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special><</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span> + <span class=identifier><b>holder</b></span><span class=special><</span><span class=identifier>custom_holder_specifier</span><span class=special>></span> +<span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> +</pre></blockquote> + +<h2><a name="locking">Custom locking policies</a></h2> + +<p> +A custom locking policy presents the following simple interface: +</p> + +<blockquote><pre> +<span class=comment>// example of a custom policy</span> + +<span class=keyword>class</span> <span class=identifier>custom_locking</span> +<span class=special>{</span> + <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>mutex_type</span><span class=special>;</span> + <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>lock_type</span><span class=special>;</span> +<span class=special>};</span> +</pre></blockquote> + +<p> +where <code>lock_type</code> is used to acquire/release mutexes according to +the <i>scoped lock</i> idiom: +</p> + +<blockquote><pre> +<span class=identifier>mutex_type</span> <span class=identifier>m</span><span class=special>;</span> +<span class=special>...</span> +<span class=special>{</span> + <span class=identifier>lock_type</span> <span class=identifier>lk</span><span class=special>(</span><span class=identifier>m</span><span class=special>);</span> <span class=comment>// acquire the mutex + // zone of mutual exclusion, no other thread can acquire the mutex</span> + <span class=special>...</span> +<span class=special>}</span> <span class=comment>// m released at lk destruction</span> +</pre></blockquote> + +<p> +Formal definitions for the concepts +<a href="../reference/locking.html#preliminary"><code>Mutex</code></a> and +<a href="../reference/locking.html#preliminary"><code>Scoped Lock</code></a> +are given at the reference. To pass a locking policy as a template argument of +<code>flyweight</code>, the class must be appropriately tagged: +</p> + +<blockquote><pre> +<span class=comment>// Alternatives for tagging a locking policy</span> + +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>locking_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> + +<span class=comment>// 1: Have the policy derive from locking_marker</span> + +<span class=keyword>struct</span> <span class=identifier>custom_locking</span><span class=special>:</span> <span class=identifier>locking_marker</span> +<span class=special>{</span> + <span class=special>...</span> +<span class=special>};</span> + +<span class=comment>// 2: Specialize the is_locking class template</span> + +<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> +<span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> + +<span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_locking</span><span class=special><</span><span class=identifier>custom_locking</span><span class=special>>:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span> + +<span class=special>}}</span> + +<span class=comment>// 3: use the locking<> wrapper when passing the policy +// to flyweight</span> + +<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special><</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span> + <span class=identifier>locking</span><span class=special><</span><span class=identifier>custom_locking</span><span class=special>></span> +<span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> +</pre></blockquote> + +<p> +Note that a locking policy is its own specifier, i.e. there is no +additional class to be passed as a proxy for the real component as is +the case with factories and holders. +</p> + +<h2><a name="tracking">Custom tracking policies</a></h2> + +<p> +Tracking policies contribute some type information to the process of +definition of the internal flyweight factory, and are given access +to that factory to allow for the implementation of the tracking +code. A tracking policy <code>Tracking</code> is defined as a class with +the following nested elements: +<ul> + <li>A type <code>Tracking::entry_type</code>.</li> + <li>A type <code>Tracking::handle_type</code>.</li> +</ul> +Each of these elements build on the preceding one, in the sense that +Boost.Flyweight internal machinery funnels the results produced by an +element into the following: +<ul> + <li><code>Tracking::entry_type</code> is a + <a href="lambda_expressions.html"><code>Lambda + Expression</code></a> accepting two different types named + <code>Value</code> and <code>Key</code> such that + <code>Value</code> is implicitly convertible to + <code>const Key&</code>. The expression is expected + to return + a type implicitly convertible to both <code>const Value&</code> + and <code>const Key&</code>. + <code>Tracking::entry_type</code> corresponds to the actual + type of the entries stored into the + <a href="configuration.html#factory_types">flyweight factory</a>: + by allowing the tracking policy to take part on the definition + of this type it is possible for the policy to add internal + tracking information to the entry data in case this is needed. + If no additional information is required, + the tracking policy can simply return <code>Value</code> as its + <code>Tracking::entry_type</code> type. + </li> + <li> + The binary <a href="lambda_expressions.html"><code>Lambda + Expression</code></a> <code>Tracking::handle_type</code> is invoked + with types <code>InternalHandle</code> and <code>TrackingHandler</code> + to produce a type <code>Handle</code>, which will be used as the handle + type of the flyweight factory. + <a href="../reference/tracking.html#preliminary"><code>TrackingHandler</code></a> + is passed as a template argument to <code>Tracking::handle_type</code> + to offer functionality supporting the implementation of the tracking + code. + </li> +</ul> +So, in order to define the factory of some instantiation +<code>fw_t</code> of <code>flyweight</code>, <code>Tracking::entry_type</code> +is invoked with an internal type <code>Value</code> implicitly convertible +to <code>const fw_t::key_type&</code> to obtain the entry type for the factory, +which must be convertible to both <code>const Value&</code> and +<code>const fw_t::key_type&</code>. +Then, <code>Tracking::handle_type</code> is fed an internal handle +type and a tracking policy helper to produce the factory handle type. +The observant reader might have detected an apparent circularity: +<code>Tracking::handle_type</code> produces the handle type of +the flyweight factory, and at the same time is passed a tracking helper +that grants access to the factory being defined! +The solution to this riddle comes from the realization of the fact that +<code>TrackingHandler</code> is an <i>incomplete +type</i> by the time it is passed to <code>Tracking::handle_type</code>: +only when <code>Handle</code> is instantiated at a later stage will this +type be complete. +</p> + +<p> +In order for a tracking policy to be passed to <code>flyweight</code>, +it must be tagged much in the same way as the rest of specifiers. +</p> + +<blockquote><pre> +<span class=comment>// Alternatives for tagging a tracking policy</span> + +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>tracking_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> + +<span class=comment>// 1: Have the policy derive from tracking_marker</span> + +<span class=keyword>struct</span> <span class=identifier>custom_tracking</span><span class=special>:</span> <span class=identifier><b>tracking_marker</b></span> +<span class=special>{</span> + <span class=special>...</span> +<span class=special>};</span> + +<span class=comment>// 2: Specialize the is_tracking class template</span> + +<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> +<span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> + +<span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_tracking</span><span class=special><</span><span class=identifier>custom_tracking</span><span class=special>>:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span> + +<span class=special>}}</span> + +<span class=comment>// 3: use the tracking<> wrapper when passing the policy +// to flyweight</span> + +<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special><</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span> + <span class=identifier><b>tracking</b></span><span class=special><</span><span class=identifier>custom_tracking</span><span class=special>></span> +<span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> +</pre></blockquote> + +<p> +Tracking policies are their own specifiers, that is, they are provided directly +as template arguments to the <code>flyweight</code> class template. +</p> + +<hr> + +<div class="prev_link"><a href="configuration.html"><img src="../prev.gif" alt="configuring Boost.Flyweight" border="0"><br> +Configuring Boost.Flyweight +</a></div> +<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br> +Boost.Flyweight tutorial +</a></div> +<div class="next_link"><a href="technical.html"><img src="../next.gif" alt="technical issues" border="0"><br> +Technical issues +</a></div><br clear="all" style="clear: all;"> + +<br> + +<p>Revised December 2nd 2008</p> + +<p>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/tutorial/flyweight_rep.png b/libs/flyweight/doc/tutorial/flyweight_rep.png Binary files differnew file mode 100644 index 000000000..860728a09 --- /dev/null +++ b/libs/flyweight/doc/tutorial/flyweight_rep.png diff --git a/libs/flyweight/doc/tutorial/index.html b/libs/flyweight/doc/tutorial/index.html new file mode 100644 index 000000000..28b46807f --- /dev/null +++ b/libs/flyweight/doc/tutorial/index.html @@ -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<T></code> is an opaque type convertible to +<code>const T&</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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/tutorial/key_value.html b/libs/flyweight/doc/tutorial/key_value.html new file mode 100644 index 000000000..ddcb35658 --- /dev/null +++ b/libs/flyweight/doc/tutorial/key_value.html @@ -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>&</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>&</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<texture></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><</span><span class=identifier>texture</span><span class=special>></span> <span class=identifier>fw</span><span class=special>(</span><span class=string>"grass.texture"</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><</span><span class=identifier>texture</span><span class=special>></span> <span class=identifier>fw</span><span class=special>(</span><span class=identifier>texture</span><span class=special>(</span><span class=string>"grass.texture"</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<T></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><</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>></span> +<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>key_value</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></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>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=special>></span> <span class=identifier>fw</span><span class=special>(</span><span class=string>"grass.texture"</span><span class=special>);</span> +</pre></blockquote> + +<p> +So called <i>key-value flyweights</i> have then the form +<code>flyweight<key_value<K,T> ></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>&</span> <span class=identifier>get_texture</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>object</span><span class=special>&);</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>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=special>></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 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<Key,Value>::rep_type::no_key_from_value_failure:: +<b>NO_KEY_FROM_VALUE_CONVERSION_PROVIDED</b>::* ***********)(std::string,texture)' +to 'boost::mpl::assert<false>::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>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>texture</span><span class=special>&</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><</span><span class=identifier>key_value</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span><span class=identifier>texture</span><span class=special>,</span><span class=identifier>texture_filename_extractor</span><span class=special>></span> <span class=special>></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<key_value<K,T> ></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 February 21st 2009</p> + +<p>© Copyright 2006-2009 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/tutorial/lambda_expressions.html b/libs/flyweight/doc/tutorial/lambda_expressions.html new file mode 100644 index 000000000..c89b2ea39 --- /dev/null +++ b/libs/flyweight/doc/tutorial/lambda_expressions.html @@ -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><</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>></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<Arg1,Arg2></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><</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>struct</span> <span class=identifier>apply</span> + <span class=special>{</span> + <span class=comment>// this is the "return type" of foo_specifier</span> + <span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special><</span><span class=identifier>Arg1</span><span class=special>,</span><span class=identifier>Arg2</span><span class=special>></span> <span class=identifier>type</span><span class=special>;</span> + <span class=special>};</span> +<span class=special>};</span> +</pre></blockquote> + </li> + <li> + 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><</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>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<std::string></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><</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>struct</span> <span class=identifier>apply</span><span class=special>{</span><span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special><</span><span class=identifier>Arg2</span><span class=special>,</span><span class=identifier>Arg1</span><span class=special>></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><</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>></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><</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>struct</span> <span class=identifier>apply</span><span class=special>{</span><span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special><</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special><</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><</span><span class=identifier>Arg2</span><span class=special>></span> <span class=special>></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><</span> + <span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special><</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>>,</span> + <span class=identifier>std</span><span class=special>::</span><span class=identifier>less</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=special>></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><</span><span class=keyword>typename</span> <span class=identifier>Arg1</span><span class=special>></span> + <span class=keyword>struct</span> <span class=identifier>apply</span><span class=special>{</span><span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special><</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><</span><span class=identifier>Arg1</span><span class=special>></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><</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><</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=special>></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><</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>struct</span> <span class=identifier>apply</span><span class=special>{</span><span class=keyword>typedef</span> <span class=identifier>foo</span><span class=special><</span><span class=identifier>Arg1</span><span class=special>,</span><span class=identifier>foo</span><span class=special><</span><span class=identifier>Arg2</span><span class=special>,</span><span class=identifier>Arg3</span><span class=special>></span> <span class=special>></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><</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><</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>></span> <span class=special>></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>© Copyright 2006-2008 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/tutorial/technical.html b/libs/flyweight/doc/tutorial/technical.html new file mode 100644 index 000000000..8bf242bfd --- /dev/null +++ b/libs/flyweight/doc/tutorial/technical.html @@ -0,0 +1,199 @@ +<!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<T></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<T></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<T></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><</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><</span><span class=identifier>thread</span><span class=special>>(</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<std::string></span> + <span class=special>}</span> + <span class=identifier>array</span><span class=special><</span><span class=identifier>shared_ptr</span><span class=special><</span><span class=identifier>thread</span><span class=special>>,</span><span class=number>100</span><span class=special>></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<std::string></code>. +Static data initialization can potentially be executed twice concurrently +if two threads happen to collide on the first usage of +<code>flyweight<std::string></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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>::</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><</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><</span><span class=identifier>thread</span><span class=special>>(</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<T>::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><</span><span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=special>></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 when exiting. For instance, if run +from Microsoft Visual C++ environment in debug mode, a breakpoint is triggered +at termination time and the debug output window shows a message along the following: +</p> + +<blockquote><pre> +HEAP[test.exe]: HEAP: Free Heap block 3a6488 modified at 3a6650 after it was +freed +Windows has triggered a breakpoint in test.exe. +This may be due to a corruption of the heap, and indicates a bug in test.exe +or any of the DLLs it has loaded. +The output window may have more diagnostic information +</pre></blockquote> + +<p> +What is the problem? Although the type of <code>v</code> involves +<code>flyweight<std::string></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<std::string></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<std::string></code> before <code>v</code> is +created. Here, calling +the function <code>flyweight<std::string>::init</code> is a little +cumbersome, so we can resort to the utility type +<code>flyweight<std::string>::initializer</code> to do that job for us: +</p> + +<blockquote><pre> +<span class=comment>// equivalent to calling flyweight<std::string>::init()</span> +<b><span class=keyword>static</span> <span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>::</span><span class=identifier>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><</span><span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=special>></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 Octber 16th 2010</p> + +<p>© Copyright 2006-2010 Joaquín M López Muñoz. +Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +http://www.boost.org/LICENSE_1_0.txt</a>) +</p> + +</body> +</html> diff --git a/libs/flyweight/doc/up.gif b/libs/flyweight/doc/up.gif Binary files differnew file mode 100644 index 000000000..acb377777 --- /dev/null +++ b/libs/flyweight/doc/up.gif diff --git a/libs/flyweight/example/Jamfile.v2 b/libs/flyweight/example/Jamfile.v2 new file mode 100644 index 000000000..b329a6c84 --- /dev/null +++ b/libs/flyweight/example/Jamfile.v2 @@ -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 + ; diff --git a/libs/flyweight/example/basic.cpp b/libs/flyweight/example/basic.cpp new file mode 100644 index 000000000..405dff721 --- /dev/null +++ b/libs/flyweight/example/basic.cpp @@ -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; +} diff --git a/libs/flyweight/example/composite.cpp b/libs/flyweight/example/composite.cpp new file mode 100644 index 000000000..8dcb2d716 --- /dev/null +++ b/libs/flyweight/example/composite.cpp @@ -0,0 +1,177 @@ +/* Boost.Flyweight example of a composite design. + * + * Copyright 2006-2010 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 list_elems& elms)const + { + 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; +} diff --git a/libs/flyweight/example/custom_factory.cpp b/libs/flyweight/example/custom_factory.cpp new file mode 100644 index 000000000..3b9b2d889 --- /dev/null +++ b/libs/flyweight/example/custom_factory.cpp @@ -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; +} diff --git a/libs/flyweight/example/fibonacci.cpp b/libs/flyweight/example/fibonacci.cpp new file mode 100644 index 000000000..618c5f2f0 --- /dev/null +++ b/libs/flyweight/example/fibonacci.cpp @@ -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; +} diff --git a/libs/flyweight/example/html.cpp b/libs/flyweight/example/html.cpp new file mode 100644 index 000000000..a428f1e64 --- /dev/null +++ b/libs/flyweight/example/html.cpp @@ -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; +} diff --git a/libs/flyweight/example/key_value.cpp b/libs/flyweight/example/key_value.cpp new file mode 100644 index 000000000..5a93d07fe --- /dev/null +++ b/libs/flyweight/example/key_value.cpp @@ -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; +} diff --git a/libs/flyweight/example/perf.cpp b/libs/flyweight/example/perf.cpp new file mode 100644 index 000000000..3e608c0db --- /dev/null +++ b/libs/flyweight/example/perf.cpp @@ -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; +} diff --git a/libs/flyweight/index.html b/libs/flyweight/index.html new file mode 100644 index 000000000..1a861cf7b --- /dev/null +++ b/libs/flyweight/index.html @@ -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> diff --git a/libs/flyweight/test/Jamfile.v2 b/libs/flyweight/test/Jamfile.v2 new file mode 100644 index 000000000..62a5b4470 --- /dev/null +++ b/libs/flyweight/test/Jamfile.v2 @@ -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 ; diff --git a/libs/flyweight/test/heavy_objects.hpp b/libs/flyweight/test/heavy_objects.hpp new file mode 100644 index 000000000..11a97d0e9 --- /dev/null +++ b/libs/flyweight/test/heavy_objects.hpp @@ -0,0 +1,106 @@ +/* Classes for Boost.Flyweight key-value tests. + * + * Copyright 2006-2009 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/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#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; +}; + +#if !defined(BOOST_NO_EXCEPTIONS) +struct throwing_value_exception{}; + +struct throwing_value +{ + throwing_value():n(0){} + throwing_value(const throwing_value&){throw throwing_value_exception();} + throwing_value(int){throw throwing_value_exception();} + + int n; +}; + +struct from_throwing_value_to_int +{ + const int& operator()(const throwing_value& x)const{return x.n;} +}; +#endif + +#endif diff --git a/libs/flyweight/test/intermod_holder_dll.cpp b/libs/flyweight/test/intermod_holder_dll.cpp new file mode 100644 index 000000000..098bca322 --- /dev/null +++ b/libs/flyweight/test/intermod_holder_dll.cpp @@ -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); +} diff --git a/libs/flyweight/test/intermod_holder_dll.hpp b/libs/flyweight/test/intermod_holder_dll.hpp new file mode 100644 index 000000000..b48edc784 --- /dev/null +++ b/libs/flyweight/test/intermod_holder_dll.hpp @@ -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 diff --git a/libs/flyweight/test/test_all_main.cpp b/libs/flyweight/test/test_all_main.cpp new file mode 100644 index 000000000..709a8b3fe --- /dev/null +++ b/libs/flyweight/test/test_all_main.cpp @@ -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(); +} diff --git a/libs/flyweight/test/test_assoc_cont_fact_main.cpp b/libs/flyweight/test/test_assoc_cont_fact_main.cpp new file mode 100644 index 000000000..1b3e7b71d --- /dev/null +++ b/libs/flyweight/test/test_assoc_cont_fact_main.cpp @@ -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(); +} diff --git a/libs/flyweight/test/test_assoc_cont_factory.cpp b/libs/flyweight/test/test_assoc_cont_factory.cpp new file mode 100644 index 000000000..cac11c98b --- /dev/null +++ b/libs/flyweight/test/test_assoc_cont_factory.cpp @@ -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>(); +} diff --git a/libs/flyweight/test/test_assoc_cont_factory.hpp b/libs/flyweight/test/test_assoc_cont_factory.hpp new file mode 100644 index 000000000..e9aa9313d --- /dev/null +++ b/libs/flyweight/test/test_assoc_cont_factory.hpp @@ -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(); diff --git a/libs/flyweight/test/test_basic.cpp b/libs/flyweight/test/test_basic.cpp new file mode 100644 index 000000000..53285ec22 --- /dev/null +++ b/libs/flyweight/test/test_basic.cpp @@ -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>(); +} diff --git a/libs/flyweight/test/test_basic.hpp b/libs/flyweight/test/test_basic.hpp new file mode 100644 index 000000000..d7d86d5f1 --- /dev/null +++ b/libs/flyweight/test/test_basic.hpp @@ -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(); diff --git a/libs/flyweight/test/test_basic_main.cpp b/libs/flyweight/test/test_basic_main.cpp new file mode 100644 index 000000000..b2508d85c --- /dev/null +++ b/libs/flyweight/test/test_basic_main.cpp @@ -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(); +} diff --git a/libs/flyweight/test/test_basic_template.hpp b/libs/flyweight/test/test_basic_template.hpp new file mode 100644 index 000000000..7829f7f91 --- /dev/null +++ b/libs/flyweight/test/test_basic_template.hpp @@ -0,0 +1,247 @@ +/* Boost.Flyweight basic test template. + * + * Copyright 2006-2009 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]); + +#if !defined(BOOST_NO_EXCEPTIONS) + typedef typename boost::mpl::apply1< + FlyweightSpecifier, + boost::flyweights::key_value<int,throwing_value,from_throwing_value_to_int> + >::type throwing_flyweight; + + try{ + throwing_flyweight fw(0); + }catch(const throwing_value_exception&){} + try{ + throwing_flyweight fw=throwing_flyweight(throwing_value()); + }catch(const throwing_value_exception&){} +#endif + +} + +#undef LENGTHOF + +#endif diff --git a/libs/flyweight/test/test_custom_factory.cpp b/libs/flyweight/test/test_custom_factory.cpp new file mode 100644 index 000000000..9fec1b408 --- /dev/null +++ b/libs/flyweight/test/test_custom_factory.cpp @@ -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>(); +} diff --git a/libs/flyweight/test/test_custom_factory.hpp b/libs/flyweight/test/test_custom_factory.hpp new file mode 100644 index 000000000..5b17deb16 --- /dev/null +++ b/libs/flyweight/test/test_custom_factory.hpp @@ -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(); diff --git a/libs/flyweight/test/test_custom_factory_main.cpp b/libs/flyweight/test/test_custom_factory_main.cpp new file mode 100644 index 000000000..95067035d --- /dev/null +++ b/libs/flyweight/test/test_custom_factory_main.cpp @@ -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(); +} diff --git a/libs/flyweight/test/test_init.cpp b/libs/flyweight/test/test_init.cpp new file mode 100644 index 000000000..118e51baf --- /dev/null +++ b/libs/flyweight/test/test_init.cpp @@ -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); +} diff --git a/libs/flyweight/test/test_init.hpp b/libs/flyweight/test/test_init.hpp new file mode 100644 index 000000000..4e869f540 --- /dev/null +++ b/libs/flyweight/test/test_init.hpp @@ -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(); diff --git a/libs/flyweight/test/test_init_main.cpp b/libs/flyweight/test/test_init_main.cpp new file mode 100644 index 000000000..213e50513 --- /dev/null +++ b/libs/flyweight/test/test_init_main.cpp @@ -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(); +} diff --git a/libs/flyweight/test/test_intermod_holder.cpp b/libs/flyweight/test/test_intermod_holder.cpp new file mode 100644 index 000000000..65ca1c1d9 --- /dev/null +++ b/libs/flyweight/test/test_intermod_holder.cpp @@ -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")); +} diff --git a/libs/flyweight/test/test_intermod_holder.hpp b/libs/flyweight/test/test_intermod_holder.hpp new file mode 100644 index 000000000..01495b3be --- /dev/null +++ b/libs/flyweight/test/test_intermod_holder.hpp @@ -0,0 +1,11 @@ +/* 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. + */ + +void test_intermodule_holder(); diff --git a/libs/flyweight/test/test_intermod_holder_main.cpp b/libs/flyweight/test/test_intermod_holder_main.cpp new file mode 100644 index 000000000..11519cdc9 --- /dev/null +++ b/libs/flyweight/test/test_intermod_holder_main.cpp @@ -0,0 +1,18 @@ +/* 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 <boost/detail/lightweight_test.hpp> +#include "test_intermod_holder.hpp" + +int main() +{ + test_intermodule_holder(); + return boost::report_errors(); +} diff --git a/libs/flyweight/test/test_multictor.cpp b/libs/flyweight/test/test_multictor.cpp new file mode 100644 index 000000000..6f326f23a --- /dev/null +++ b/libs/flyweight/test/test_multictor.cpp @@ -0,0 +1,105 @@ +/* Boost.Flyweight test of flyweight forwarding ctors. + * + * 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_multictor.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/detail/workaround.hpp> +#include <boost/flyweight.hpp> +#include <boost/functional/hash.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/tuple/tuple_comparison.hpp> +#include "test_basic_template.hpp" + +using boost::flyweight; + +#if BOOST_WORKAROUND(BOOST_MSVC,<1300) +#define NONCONST const +#else +#define NONCONST +#endif + +struct multictor +{ + typedef multictor type; + + multictor(): + t(0,0,0.0,"",false){} + multictor(NONCONST int& x0): + t(x0,0,0.0,"",false){} + multictor(int x0,NONCONST char& x1): + t(x0,x1,0.0,"",false){} + multictor(int x0,char x1,NONCONST double& x2): + t(x0,x1,x2,"",false){} + multictor(int x0,char x1,double x2,NONCONST std::string& x3): + t(x0,x1,x2,x3,false){} + multictor(int x0,char x1,double x2,const std::string& x3,NONCONST bool& x4): + t(x0,x1,x2,x3,x4){} + + friend bool operator==(const type& x,const type& y){return x.t==y.t;} + friend bool operator< (const type& x,const type& y){return x.t< y.t;} + friend bool operator!=(const type& x,const type& y){return x.t!=y.t;} + friend bool operator> (const type& x,const type& y){return x.t> y.t;} + friend bool operator>=(const type& x,const type& y){return x.t>=y.t;} + friend bool operator<=(const type& x,const type& y){return x.t<=y.t;} + + boost::tuples::tuple<int,char,double,std::string,bool> t; +}; + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +namespace boost{ +#endif + +inline std::size_t hash_value(const multictor& x) +{ + std::size_t res=0; + boost::hash_combine(res,boost::tuples::get<0>(x.t)); + boost::hash_combine(res,boost::tuples::get<1>(x.t)); + boost::hash_combine(res,boost::tuples::get<2>(x.t)); + boost::hash_combine(res,boost::tuples::get<3>(x.t)); + boost::hash_combine(res,boost::tuples::get<4>(x.t)); + return res; +} + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +} /* namespace boost */ +#endif + +void test_multictor() +{ + flyweight<multictor> f; + multictor m; + BOOST_TEST(f==m); + + int x0=1; + flyweight<multictor> f0(x0); + multictor m0(x0); + BOOST_TEST(f0==m0); + + char x1='a'; + flyweight<multictor> f1(1,x1); + multictor m1(1,x1); + BOOST_TEST(f1==m1); + + double x2=3.1416; + flyweight<multictor> f2(1,'a',x2); + multictor m2(1,'a',x2); + BOOST_TEST(f2==m2); + + std::string x3("boost"); + flyweight<multictor> f3(1,'a',3.1416,x3); + multictor m3(1,'a',3.1416,x3); + BOOST_TEST(f3==m3); + + bool x4=true; + flyweight<multictor> f4(1,'a',3.1416,"boost",x4); + multictor m4(1,'a',3.1416,"boost",x4); + BOOST_TEST(f4==m4); +} diff --git a/libs/flyweight/test/test_multictor.hpp b/libs/flyweight/test/test_multictor.hpp new file mode 100644 index 000000000..125cc9289 --- /dev/null +++ b/libs/flyweight/test/test_multictor.hpp @@ -0,0 +1,11 @@ +/* Boost.Flyweight test of flyweight forwarding ctors. + * + * 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_multictor(); diff --git a/libs/flyweight/test/test_multictor_main.cpp b/libs/flyweight/test/test_multictor_main.cpp new file mode 100644 index 000000000..090aa3e6f --- /dev/null +++ b/libs/flyweight/test/test_multictor_main.cpp @@ -0,0 +1,18 @@ +/* Boost.Flyweight test of flyweight forwarding ctors. + * + * 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_multictor.hpp" + +int main() +{ + test_multictor(); + return boost::report_errors(); +} diff --git a/libs/flyweight/test/test_no_locking.cpp b/libs/flyweight/test/test_no_locking.cpp new file mode 100644 index 000000000..a9b493c05 --- /dev/null +++ b/libs/flyweight/test/test_no_locking.cpp @@ -0,0 +1,35 @@ +/* Boost.Flyweight test of no_locking. + * + * 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_no_locking.hpp" + +#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/no_locking.hpp> +#include <boost/flyweight/refcounted.hpp> +#include <boost/flyweight/static_holder.hpp> +#include "test_basic_template.hpp" + +using namespace boost::flyweights; + +struct no_locking_flyweight_specifier +{ + template<typename T> + struct apply + { + typedef flyweight<T,no_locking> type; + }; +}; + +void test_no_locking() +{ + test_basic_template<no_locking_flyweight_specifier>(); +} diff --git a/libs/flyweight/test/test_no_locking.hpp b/libs/flyweight/test/test_no_locking.hpp new file mode 100644 index 000000000..a18470da4 --- /dev/null +++ b/libs/flyweight/test/test_no_locking.hpp @@ -0,0 +1,11 @@ +/* Boost.Flyweight test of no_locking. + * + * 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_no_locking(); diff --git a/libs/flyweight/test/test_no_locking_main.cpp b/libs/flyweight/test/test_no_locking_main.cpp new file mode 100644 index 000000000..85d2b090e --- /dev/null +++ b/libs/flyweight/test/test_no_locking_main.cpp @@ -0,0 +1,18 @@ +/* Boost.Flyweight test of no_locking. + * + * 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_no_locking.hpp" + +int main() +{ + test_no_locking(); + return boost::report_errors(); +} diff --git a/libs/flyweight/test/test_no_tracking.cpp b/libs/flyweight/test/test_no_tracking.cpp new file mode 100644 index 000000000..876578173 --- /dev/null +++ b/libs/flyweight/test/test_no_tracking.cpp @@ -0,0 +1,35 @@ +/* Boost.Flyweight test of no_tracking. + * + * 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_no_tracking.hpp" + +#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/no_tracking.hpp> +#include <boost/flyweight/simple_locking.hpp> +#include <boost/flyweight/static_holder.hpp> +#include "test_basic_template.hpp" + +using namespace boost::flyweights; + +struct no_tracking_flyweight_specifier +{ + template<typename T> + struct apply + { + typedef flyweight<T,no_tracking> type; + }; +}; + +void test_no_tracking() +{ + test_basic_template<no_tracking_flyweight_specifier>(); +} diff --git a/libs/flyweight/test/test_no_tracking.hpp b/libs/flyweight/test/test_no_tracking.hpp new file mode 100644 index 000000000..99613731a --- /dev/null +++ b/libs/flyweight/test/test_no_tracking.hpp @@ -0,0 +1,11 @@ +/* Boost.Flyweight test of no_tracking. + * + * 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_no_tracking(); diff --git a/libs/flyweight/test/test_no_tracking_main.cpp b/libs/flyweight/test/test_no_tracking_main.cpp new file mode 100644 index 000000000..1cc9decd2 --- /dev/null +++ b/libs/flyweight/test/test_no_tracking_main.cpp @@ -0,0 +1,18 @@ +/* Boost.Flyweight test of no_tracking. + * + * 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_no_tracking.hpp" + +int main() +{ + test_no_tracking(); + return boost::report_errors(); +} diff --git a/libs/flyweight/test/test_set_factory.cpp b/libs/flyweight/test/test_set_factory.cpp new file mode 100644 index 000000000..eff0b9cfb --- /dev/null +++ b/libs/flyweight/test/test_set_factory.cpp @@ -0,0 +1,71 @@ +/* Boost.Flyweight test of set_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_set_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/set_factory.hpp> +#include <boost/flyweight/simple_locking.hpp> +#include <boost/flyweight/static_holder.hpp> +#include "test_basic_template.hpp" + +using namespace boost::flyweights; + +struct set_factory_flyweight_specifier1 +{ + template<typename T> + struct apply + { + typedef flyweight<T,set_factory<> > type; + }; +}; + +struct set_factory_flyweight_specifier2 +{ + template<typename T> + struct apply + { + typedef flyweight< + T, + static_holder_class<boost::mpl::_1>, + set_factory_class< + boost::mpl::_1,boost::mpl::_2, + std::greater<boost::mpl::_2>, + std::allocator<boost::mpl::_1> + > + > type; + }; +}; + +struct set_factory_flyweight_specifier3 +{ + template<typename T> + struct apply + { + typedef flyweight< + T, + set_factory< + std::greater<boost::mpl::_2>, + std::allocator<boost::mpl::_1> + >, + static_holder_class<boost::mpl::_1>, + tag<char> + > type; + }; +}; + +void test_set_factory() +{ + test_basic_template<set_factory_flyweight_specifier1>(); + test_basic_template<set_factory_flyweight_specifier2>(); + test_basic_template<set_factory_flyweight_specifier3>(); +} diff --git a/libs/flyweight/test/test_set_factory.hpp b/libs/flyweight/test/test_set_factory.hpp new file mode 100644 index 000000000..6e783e3a2 --- /dev/null +++ b/libs/flyweight/test/test_set_factory.hpp @@ -0,0 +1,11 @@ +/* Boost.Flyweight test of set_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_set_factory(); diff --git a/libs/flyweight/test/test_set_factory_main.cpp b/libs/flyweight/test/test_set_factory_main.cpp new file mode 100644 index 000000000..c0e588515 --- /dev/null +++ b/libs/flyweight/test/test_set_factory_main.cpp @@ -0,0 +1,18 @@ +/* Boost.Flyweight test of set_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_set_factory.hpp" + +int main() +{ + test_set_factory(); + return boost::report_errors(); +} |