added flyweight from trunk
[SVN r50320]
96
.gitattributes
vendored
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
* text=auto !eol svneol=native#text/plain
|
||||||
|
*.gitattributes text svneol=native#text/plain
|
||||||
|
|
||||||
|
# Scriptish formats
|
||||||
|
*.bat text svneol=native#text/plain
|
||||||
|
*.bsh text svneol=native#text/x-beanshell
|
||||||
|
*.cgi text svneol=native#text/plain
|
||||||
|
*.cmd text svneol=native#text/plain
|
||||||
|
*.js text svneol=native#text/javascript
|
||||||
|
*.php text svneol=native#text/x-php
|
||||||
|
*.pl text svneol=native#text/x-perl
|
||||||
|
*.pm text svneol=native#text/x-perl
|
||||||
|
*.py text svneol=native#text/x-python
|
||||||
|
*.sh eol=lf svneol=LF#text/x-sh
|
||||||
|
configure eol=lf svneol=LF#text/x-sh
|
||||||
|
|
||||||
|
# Image formats
|
||||||
|
*.bmp binary svneol=unset#image/bmp
|
||||||
|
*.gif binary svneol=unset#image/gif
|
||||||
|
*.ico binary svneol=unset#image/ico
|
||||||
|
*.jpeg binary svneol=unset#image/jpeg
|
||||||
|
*.jpg binary svneol=unset#image/jpeg
|
||||||
|
*.png binary svneol=unset#image/png
|
||||||
|
*.tif binary svneol=unset#image/tiff
|
||||||
|
*.tiff binary svneol=unset#image/tiff
|
||||||
|
*.svg text svneol=native#image/svg%2Bxml
|
||||||
|
|
||||||
|
# Data formats
|
||||||
|
*.pdf binary svneol=unset#application/pdf
|
||||||
|
*.avi binary svneol=unset#video/avi
|
||||||
|
*.doc binary svneol=unset#application/msword
|
||||||
|
*.dsp text svneol=crlf#text/plain
|
||||||
|
*.dsw text svneol=crlf#text/plain
|
||||||
|
*.eps binary svneol=unset#application/postscript
|
||||||
|
*.gz binary svneol=unset#application/gzip
|
||||||
|
*.mov binary svneol=unset#video/quicktime
|
||||||
|
*.mp3 binary svneol=unset#audio/mpeg
|
||||||
|
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
|
||||||
|
*.ps binary svneol=unset#application/postscript
|
||||||
|
*.psd binary svneol=unset#application/photoshop
|
||||||
|
*.rdf binary svneol=unset#text/rdf
|
||||||
|
*.rss text svneol=unset#text/xml
|
||||||
|
*.rtf binary svneol=unset#text/rtf
|
||||||
|
*.sln text svneol=native#text/plain
|
||||||
|
*.swf binary svneol=unset#application/x-shockwave-flash
|
||||||
|
*.tgz binary svneol=unset#application/gzip
|
||||||
|
*.vcproj text svneol=native#text/xml
|
||||||
|
*.vcxproj text svneol=native#text/xml
|
||||||
|
*.vsprops text svneol=native#text/xml
|
||||||
|
*.wav binary svneol=unset#audio/wav
|
||||||
|
*.xls binary svneol=unset#application/vnd.ms-excel
|
||||||
|
*.zip binary svneol=unset#application/zip
|
||||||
|
|
||||||
|
# Text formats
|
||||||
|
.htaccess text svneol=native#text/plain
|
||||||
|
*.bbk text svneol=native#text/xml
|
||||||
|
*.cmake text svneol=native#text/plain
|
||||||
|
*.css text svneol=native#text/css
|
||||||
|
*.dtd text svneol=native#text/xml
|
||||||
|
*.htm text svneol=native#text/html
|
||||||
|
*.html text svneol=native#text/html
|
||||||
|
*.ini text svneol=native#text/plain
|
||||||
|
*.log text svneol=native#text/plain
|
||||||
|
*.mak text svneol=native#text/plain
|
||||||
|
*.qbk text svneol=native#text/plain
|
||||||
|
*.rst text svneol=native#text/plain
|
||||||
|
*.sql text svneol=native#text/x-sql
|
||||||
|
*.txt text svneol=native#text/plain
|
||||||
|
*.xhtml text svneol=native#text/xhtml%2Bxml
|
||||||
|
*.xml text svneol=native#text/xml
|
||||||
|
*.xsd text svneol=native#text/xml
|
||||||
|
*.xsl text svneol=native#text/xml
|
||||||
|
*.xslt text svneol=native#text/xml
|
||||||
|
*.xul text svneol=native#text/xul
|
||||||
|
*.yml text svneol=native#text/plain
|
||||||
|
boost-no-inspect text svneol=native#text/plain
|
||||||
|
CHANGES text svneol=native#text/plain
|
||||||
|
COPYING text svneol=native#text/plain
|
||||||
|
INSTALL text svneol=native#text/plain
|
||||||
|
Jamfile text svneol=native#text/plain
|
||||||
|
Jamroot text svneol=native#text/plain
|
||||||
|
Jamfile.v2 text svneol=native#text/plain
|
||||||
|
Jamrules text svneol=native#text/plain
|
||||||
|
Makefile* text svneol=native#text/plain
|
||||||
|
README text svneol=native#text/plain
|
||||||
|
TODO text svneol=native#text/plain
|
||||||
|
|
||||||
|
# Code formats
|
||||||
|
*.c text svneol=native#text/plain
|
||||||
|
*.cpp text svneol=native#text/plain
|
||||||
|
*.h text svneol=native#text/plain
|
||||||
|
*.hpp text svneol=native#text/plain
|
||||||
|
*.ipp text svneol=native#text/plain
|
||||||
|
*.tpp text svneol=native#text/plain
|
||||||
|
*.jam text svneol=native#text/plain
|
||||||
|
*.java text svneol=native#text/plain
|
||||||
88
doc/acknowledgements.html
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Acknowledgements</title>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css">
|
||||||
|
<link rel="start" href="index.html">
|
||||||
|
<link rel="prev" href="release_notes.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Acknowledgements</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="release_notes.html"><img src="prev.gif" alt="release notes" border="0"><br>
|
||||||
|
Release notes
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
|
||||||
|
Index
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link">
|
||||||
|
</div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The following people have provided valuable feedback and suggestions during the
|
||||||
|
development of the library: Ion Gaztañ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>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="release_notes.html"><img src="prev.gif" alt="release notes" border="0"><br>
|
||||||
|
Release notes
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
|
||||||
|
Index
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link">
|
||||||
|
</div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p>Revised December 10th 2008</p>
|
||||||
|
|
||||||
|
<p>© 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>
|
||||||
258
doc/examples.html
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Examples</title>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css">
|
||||||
|
<link rel="start" href="index.html">
|
||||||
|
<link rel="prev" href="performance.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="tests.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Examples</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="performance.html"><img src="prev.gif" alt="performance" border="0"><br>
|
||||||
|
Performance
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
|
||||||
|
Index
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="tests.html"><img src="next.gif" alt="tests" border="0"><br>
|
||||||
|
Tests
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
<br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#example1">Example 1: basic usage</a></li>
|
||||||
|
<li><a href="#example2">Example 2: key-value flyweights</a></li>
|
||||||
|
<li><a href="#example3">Example 3: flyweights and the composite pattern</a></li>
|
||||||
|
<li><a href="#example4">Example 4: formatted text processing</a></li>
|
||||||
|
<li><a href="#example5">Example 5: flyweight-based memoization</a></li>
|
||||||
|
<li><a href="#example6">Example 6: performance comparison</a></li>
|
||||||
|
<li><a href="#example7">Example 7: custom factory</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="example1">Example 1: basic usage</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
See <a href="../example/basic.cpp">source code</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Dummy program showing the basic capabilities of <code>flyweight</code>
|
||||||
|
explained at the <a href="tutorial/basics.html">tutorial</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2><a name="example2">Example 2: key-value flyweights</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
See <a href="../example/key_value.cpp">source code</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The program simulates the scenario described at the tutorial section on
|
||||||
|
<a href="tutorial/key_value.html">key-value flyweights</a>: The class
|
||||||
|
<code>texture</code> manages some texture rendering data stored in
|
||||||
|
a file whose location is given at construction time. The program
|
||||||
|
handles large quantities of objects of this class by encapsulating
|
||||||
|
them into key-value flyweights keyed by filename. Observe how the
|
||||||
|
execution of the program results in no extra constructions or copies
|
||||||
|
of objects of type <code>texture</code> except those absolutely
|
||||||
|
necessary.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2><a name="example3">Example 3: flyweights and the composite pattern</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
See <a href="../example/composite.cpp">source code</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The <a href="http://c2.com/cgi/wiki?CompositePattern"><i>composite
|
||||||
|
design pattern</i></a> revolves about the idea that a tree data structure
|
||||||
|
can be easily constructed and manipulated by defining the tree node type
|
||||||
|
polymorphically so that either is a leaf node or else contains a list of
|
||||||
|
pointers to their child nodes.
|
||||||
|
This way, a tree is the exact same entity as its root node, which allows
|
||||||
|
for very simple recursive tree-handling algorithms. Large composite trees
|
||||||
|
having a high degree of duplication of nodes and subtrees (as for instance
|
||||||
|
those generated when parsing a computer program) are a natural fit for the
|
||||||
|
flyweight idiom: simply turning the node type into a flyweight
|
||||||
|
automatically deals with duplication at the node and subtree level.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The example program parses Lisp-like lists of the form
|
||||||
|
<code>(a<sub>1</sub> ... a<sub><i>n</i></sub>)</code> where each
|
||||||
|
<code>a<sub>i</sub></code> is a terminal string or a list. The parsed
|
||||||
|
data structure is a composite type defined using Boost.Flyweight in conjunction
|
||||||
|
with the recursive facilities of
|
||||||
|
<a href="../../variant/index.html">Boost.Variant</a>. So, given the list
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
(= (tan (+ x y))(/ (+ (tan x)(tan y))(- 1 (* (tan x)(tan y)))))
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
the resulting data structure implicitly detects the duplicated
|
||||||
|
occurrences of <code>+</code>, <code>x</code>, <code>y</code>,
|
||||||
|
<code>tan</code>, <code>(tan x)</code> and <code>(tan y)</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2><a name="example4">Example 4: formatted text processing</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
See <a href="../example/html.cpp">source code</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A classic example of application of the flyweight pattern is that of a
|
||||||
|
text processor which handles characters with rich formatting information,
|
||||||
|
like font type, size, color and special options (boldness, italics, etc.)
|
||||||
|
Coding the formatting information of each character takes considerable
|
||||||
|
space, but, given the high degree of repetition typical in a document,
|
||||||
|
maintaining formatted characters as flyweight objects drastically reduces
|
||||||
|
memory consumption.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The example program parses, manipulates and stores HTML documents following
|
||||||
|
flyweight-based representation techniques. Given the hierarchical nature
|
||||||
|
of HTML markup, a crude approximation to the formatting options of a given
|
||||||
|
character is just to equate them with the stack of tag contexts to which
|
||||||
|
the character belongs, as the figure shows.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="html.png"
|
||||||
|
alt="formatting contexts of characters in an HTML document"
|
||||||
|
width="320" height="275"><br>
|
||||||
|
<b>Fig. 1: Formatting contexts of characters in an HTML document.</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
HTML documents are then parsed as arrays of (character, format)
|
||||||
|
pairs, where the format is the tag context as described above. The very high
|
||||||
|
degree of redundancy in formatting information is taken care of by the
|
||||||
|
use of Boost.Flyweight. This character-based representation makes it
|
||||||
|
easy to manipulate the document: transposition and elimination of
|
||||||
|
portions of text are trivial operations. As an example, the program
|
||||||
|
reverses the text occupying the central portion of the document.
|
||||||
|
Saving the result in HTML reduces to traversing the array of formatted
|
||||||
|
characters and emitting opening/closing HTML tags as the context of adjacent
|
||||||
|
characters varies.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For the sake of brevity, the HTML parsing capabilities of this program
|
||||||
|
are coarse: for instance, elements without end-tag (like <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>
|
||||||
128
doc/future_work.html
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Future work</title>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css">
|
||||||
|
<link rel="start" href="examples.html">
|
||||||
|
<link rel="prev" href="tests.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="release_notes.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Future work</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="tests.html"><img src="prev.gif" alt="examples" border="0"><br>
|
||||||
|
Tests
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
|
||||||
|
Index
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="release_notes.html"><img src="next.gif" alt="release notes" border="0"><br>
|
||||||
|
Release notes
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
<br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
New functionalities can be included into future releases of Boost.Flyweight
|
||||||
|
to meet the demands of users and to leverage upcoming C++0x features
|
||||||
|
and new Boost libraries. The following is a list of candidate additions.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#instrospection">Introspection API</a></li>
|
||||||
|
<li><a href="#perfect_fwd">Perfect forwarding</a></li>
|
||||||
|
<li><a href="#rw_lock">Read/write locking policy</a></li>
|
||||||
|
<li><a href="#new_boost_libs">Integration with new Boost libraries</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="instrospection">Introspection API</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Currently there is no way to access the internal components of a
|
||||||
|
<code>flyweight</code> instantiation (factory, holder, etc.) or even
|
||||||
|
to know the types of these components. With such an API it would be
|
||||||
|
possible to instrument and monitor the usage of Boost.Flyweight like in
|
||||||
|
the following example:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special><</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>
|
||||||
BIN
doc/html.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
82
doc/index.html
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Index</title>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css">
|
||||||
|
<link rel="start" href="index.html">
|
||||||
|
<link rel="next" href="tutorial/index.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost Flyweight Library</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"></div>
|
||||||
|
<div class="up_link"></div>
|
||||||
|
<div class="next_link"><a href="tutorial/index.html"><img src="next.gif" alt="tutorial" border="0"><br>
|
||||||
|
Tutorial
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Flyweights are small-sized handle classes granting constant access to shared
|
||||||
|
common data, thus allowing for the management of large amounts of entities
|
||||||
|
within reasonable memory limits. Boost.Flyweight makes it easy to use this
|
||||||
|
common programming idiom by providing the class template
|
||||||
|
<code>flyweight<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>
|
||||||
BIN
doc/memory.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
doc/memory_gcc_344.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
doc/memory_msvc_80.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
doc/next.gif
Normal file
|
After Width: | Height: | Size: 852 B |
472
doc/performance.html
Normal file
@@ -0,0 +1,472 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Performance</title>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css">
|
||||||
|
<link rel="start" href="index.html">
|
||||||
|
<link rel="prev" href="reference/tracking.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="examples.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Performance</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="reference/tracking.html"><img src="prev.gif" alt="tracking policies" border="0"><br>
|
||||||
|
Tracking policies
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
|
||||||
|
Index
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="examples.html"><img src="next.gif" alt="examples" border="0"><br>
|
||||||
|
Examples
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
<br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#intro">Introduction</a></li>
|
||||||
|
<li><a href="#memory">Memory consumption</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#flyweight_size">Flyweight size</a></li>
|
||||||
|
<li><a href="#entry_size">Entry size</a></li>
|
||||||
|
<li><a href="#overall_memory">Overall memory consumption</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#time">Time efficiency</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#initialization">Initialization</a></li>
|
||||||
|
<li><a href="#assignment">Assignment</a></li>
|
||||||
|
<li><a href="#equality_comparison">Equality comparison</a></li>
|
||||||
|
<li><a href="#value_access">Value access</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#results">Experimental results</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#msvc_80">Microsoft Visual C++ 8.0</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#msvc_80_memory">Memory</a></li>
|
||||||
|
<li><a href="#msvc_80_time">Execution time</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#gcc_344">GCC 3.4.4</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#gcc_344_memory">Memory</a></li>
|
||||||
|
<li><a href="#gcc_344_time">Execution time</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#conclusions">Conclusions</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="intro">Introduction</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
We show how to estimate the memory reduction obtained by the usage of
|
||||||
|
Boost.Flyweight in a particular scenario and study the impact on the execution
|
||||||
|
time for the different functional areas of <code>flyweight</code>.
|
||||||
|
Some experimental results are provided.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2><a name="memory">Memory consumption</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
As we saw in the <a href="tutorial/index.html#rationale">tutorial rationale</a>,
|
||||||
|
the flyweight pattern is based on two types of objects:
|
||||||
|
<ul>
|
||||||
|
<li>The flyweight objects proper, which have very small size, typically
|
||||||
|
that of a pointer.
|
||||||
|
</li>
|
||||||
|
<li>The shared values, which are stored as internal <i>entries</i> into the
|
||||||
|
flyweight factory.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
The overall memory consumption is then a function of the size of the
|
||||||
|
flyweight objects, the size of the entry objects and the degree of
|
||||||
|
value redundancy.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3><a name="flyweight_size">Flyweight size</a></h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The only data member of a <code>flyweight</code> object is a so-called
|
||||||
|
<i>handle</i>, an opaque object of small size provided by the internal
|
||||||
|
flyweight factory to refer to the entries it stores. For the default
|
||||||
|
<a href="tutorial/configuration.html#hashed_factory"><code>hashed_factory</code></a>,
|
||||||
|
this handle is merely a pointer, so <code>sizeof(flyweight<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"> 1<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 2.</small>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For instance, for the default configuration parameters of <code>flyweight</code>,
|
||||||
|
<i>overhead</i> is typically 2.5(<code>hashed_factory</code>) + 1(<code>refcounted</code>)
|
||||||
|
= 3 words.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3><a name="overall_memory">Overall memory consumption</a></h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Consider a scenario where there are <i>N</i> different objects of type <code>T</code>
|
||||||
|
jointly taking <i>M</i> different values. The objects consume then
|
||||||
|
<i>S</i> = <i>N</i>·<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="322"><br>
|
||||||
|
<b>Fig. 2: Memory consumption, MSVC++ 8.0. Values in MB.</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The results show the memory consumption figures for the different profiled
|
||||||
|
scenarios.
|
||||||
|
The standard library implementation of MSVC++ 8.0 features the so-called
|
||||||
|
small buffer optimization for strings, by which <code>std::string</code>
|
||||||
|
objects hold a small buffer that can be used when the string is short,
|
||||||
|
thus avoding dynamic allocations. This results in <code>sizeof(std::string)</code>
|
||||||
|
being quite high, 28 bytes. In our particular test strings are almost always
|
||||||
|
held in the small buffer, so the minimum <a href="#overall_memory"><i>S<sub>F</sub></i> / <i>S</i></a>
|
||||||
|
achievable is 4/28 = 14.3%, which is quite close to the experimental
|
||||||
|
results, given that the memory devoted to storage of shared values
|
||||||
|
is residual (around 3% of total memory) due to the high word redundancy
|
||||||
|
of the text source.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4><a name="msvc_80_time">Execution time</a></h4>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="time_msvc_80.png" alt="execution time (s), MSVC++ 8.0"
|
||||||
|
width="820" height="324"><br>
|
||||||
|
<b>Fig. 3: Execution time, MSVC++ 8.0. Values in seconds.</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The figure displays execution times for the profiled scenarios in different
|
||||||
|
usage contexts. In accordance with our previous
|
||||||
|
<a href="#time">qualitative analysis</a>, initialization of <code>flyweight</code>s
|
||||||
|
carries an important overhead with respect to the base case scenario (between 10% and 40%
|
||||||
|
of additional execution time), while the other usage contexts
|
||||||
|
(assignment, equality comparison and value access) have performance gains,
|
||||||
|
with speedup factors of up to 14 in some cases. The use of a
|
||||||
|
<a href="tutorial/configuration.html#refcounted"><code>refcounted</code></a>
|
||||||
|
tracking policy introduces penalties with respect to
|
||||||
|
<a href="tutorial/configuration.html#no_tracking"><code>no_tracking</code></a>
|
||||||
|
in initialization and assignment, but has no effect in equality comparison
|
||||||
|
and value access.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3><a name="gcc_344">GNU GCC 3.4.4</a></h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The Cygwin/MinGW version of the compiler was used, with command options
|
||||||
|
<code>-ftemplate-depth-128 -O3 -finline-functions -DNDEBUG</code>.
|
||||||
|
Tests were run under a Cygwin terminal in the same machine as <a href="#msvc_80">before</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4><a name="gcc_344_memory">Memory</a></h4>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="memory_gcc_344.png" alt="memory consumption (MB), GCC 3.4.4"
|
||||||
|
width="798" height="322"><br>
|
||||||
|
<b>Fig. 4: Memory consumption, GCC 3.4.4. Values in MB.</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The standard library used by GCC 3.4.4 implements <code>std::string</code>
|
||||||
|
using <a href="http://en.wikipedia.org/wiki/Copy-on-write">copy-on-write</a>
|
||||||
|
optimization techniques, which leads to very small value redundancy for
|
||||||
|
some usage patterns. This explains why the memory reduction achieved
|
||||||
|
by Boost.Flyweight is so poor in this case. Other contexts where assignment
|
||||||
|
is much less used than direct construction will favor Boost.Flyweight
|
||||||
|
over plain copy-on-write <code>std::string</code>s.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4><a name="gcc_344_time">Execution time</a></h4>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="time_gcc_344.png" alt="execution time (s), GCC 3.4.4"
|
||||||
|
width="820" height="324"><br>
|
||||||
|
<b>Fig. 5: Execution time, GCC 3.4.4. Values in seconds.</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Relative performance figures are similar to those obtained for
|
||||||
|
<a href="#msvc_80_time">MSVC++ 8.0</a>, although some of the
|
||||||
|
speedups achieved by Boost.Flyweight are higher here (×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 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>
|
||||||
BIN
doc/prev.gif
Normal file
|
After Width: | Height: | Size: 852 B |
583
doc/reference/factories.html
Normal file
@@ -0,0 +1,583 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Factories reference</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="tags.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="holders.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight
|
||||||
|
Factories reference</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="tags.html"><img src="../prev.gif" alt="tags" border="0"><br>
|
||||||
|
Tags
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
|
||||||
|
Boost.Flyweight reference
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="holders.html"><img src="../next.gif" alt="holders" border="0"><br>
|
||||||
|
Holders
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#factory">Factories and factory specifiers</a></li>
|
||||||
|
<li><a href="#factory_tag_synopsis">Header
|
||||||
|
<code>"boost/flyweight/factory_tag.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#is_factory">Class template <code>is_factory</code></a></li>
|
||||||
|
<li><a href="#factory_construct">Class template <code>factory</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#hashed_factory_fwd_synopsis">Header
|
||||||
|
<code>"boost/flyweight/hashed_factory_fwd.hpp"</code> synopsis</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#hashed_factory_synopsis">Header
|
||||||
|
<code>"boost/flyweight/hashed_factory.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#hashed_factory_class">Class template <code>hashed_factory_class</code></a></li>
|
||||||
|
<li><a href="#hashed_factory">Class template <code>hashed_factory</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#set_factory_fwd_synopsis">Header
|
||||||
|
<code>"boost/flyweight/set_factory_fwd.hpp"</code> synopsis</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#set_factory_synopsis">Header
|
||||||
|
<code>"boost/flyweight/set_factory.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#set_factory_class">Class template <code>set_factory_class</code></a></li>
|
||||||
|
<li><a href="#set_factory">Class template <code>set_factory</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#assoc_container_factory_fwd_synopsis">Header
|
||||||
|
<code>"boost/flyweight/assoc_container_factory_fwd.hpp"</code> synopsis</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#assoc_container_factory_synopsis">Header
|
||||||
|
<code>"boost/flyweight/assoc_container_factory.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#assoc_container_factory_class">Class template <code>assoc_container_factory_class</code></a></li>
|
||||||
|
<li><a href="#assoc_container_factory">Class template <code>assoc_container_factory</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="factory">Factories and factory specifiers</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Given a type <code>Key</code> and an
|
||||||
|
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
|
||||||
|
type <code>Entry</code> implicitly convertible to <code>const Key&</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>
|
||||||
630
doc/reference/flyweight.html
Normal file
@@ -0,0 +1,630 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - flyweight reference</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="index.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="key_value.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight
|
||||||
|
<code>flyweight</code> reference</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.Flyweight reference" border="0"><br>
|
||||||
|
Boost.Flyweight reference
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
|
||||||
|
Boost.Flyweight reference
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="key_value.html"><img src="../next.gif" alt="key-value flyweights" border="0"><br>
|
||||||
|
Key-value flyweights
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#flyweight_fwd_synopsis">Header
|
||||||
|
<code>"boost/flyweight/flyweight_fwd.hpp"</code> synopsis</a></li>
|
||||||
|
<li><a href="#synopsis">Header
|
||||||
|
<code>"boost/flyweight/flyweight.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#flyweight">Class template <code>flyweight</code></a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#instantiation_types">Instantiation types</a></li>
|
||||||
|
<li><a href="#static_init">Static data initialization</a></li>
|
||||||
|
<li><a href="#constructors">Constructors, copy and assignment</a></li>
|
||||||
|
<li><a href="#convertibility">Convertibility to the underlying types</a></li>
|
||||||
|
<li><a href="#modifiers">Modifiers</a></li>
|
||||||
|
<li><a href="#comparison">Comparison operators</a></li>
|
||||||
|
<li><a href="#specialized">Specialized algorithms</a></li>
|
||||||
|
<li><a href="#config_macros">Configuration macros</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<a name="flyweight_fwd_synopsis">Header
|
||||||
|
<a href="../../../../boost/flyweight/flyweight_fwd.hpp"><code>"boost/flyweight/flyweight_fwd.hpp"</code></a>
|
||||||
|
synopsis</a>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
|
||||||
|
|
||||||
|
<span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span>
|
||||||
|
|
||||||
|
<span class=keyword>template</span><span class=special><</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>
|
||||||
243
doc/reference/holders.html
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Holders reference</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="factories.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="locking.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight
|
||||||
|
Holders reference</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="factories.html"><img src="../prev.gif" alt="factories" border="0"><br>
|
||||||
|
Factories
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
|
||||||
|
Boost.Flyweight reference
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="locking.html"><img src="../next.gif" alt="locking policies" border="0"><br>
|
||||||
|
Locking policies
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#holder">Holders and holder specifiers</a></li>
|
||||||
|
<li><a href="#holder_tag_synopsis">Header
|
||||||
|
<code>"boost/flyweight/holder_tag.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#is_holder">Class template <code>is_holder</code></a></li>
|
||||||
|
<li><a href="#holder_construct">Class template <code>holder</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#static_holder_fwd_synopsis">Header
|
||||||
|
<code>"boost/flyweight/static_holder_fwd.hpp"</code> synopsis</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#static_holder_synopsis">Header
|
||||||
|
<code>"boost/flyweight/static_holder.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#static_holder_class">Class template <code>static_holder_class</code></a></li>
|
||||||
|
<li><a href="#static_holder">Class <code>static_holder</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#intermodule_holder_fwd_synopsis">Header
|
||||||
|
<code>"boost/flyweight/intermodule_holder_fwd.hpp"</code> synopsis</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#intermodule_holder_synopsis">Header
|
||||||
|
<code>"boost/flyweight/intermodule_holder.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#intermodule_holder_class">Class template <code>intermodule_holder_class</code></a></li>
|
||||||
|
<li><a href="#intermodule_holder">Class <code>intermodule_holder</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="holder">Holders and holder specifiers</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Given a type <code>C</code>, a type <code>Holder</code> is said to be a <i>holder
|
||||||
|
of <code>C</code></i> if the expression <code>Holder::get()</code> returns
|
||||||
|
a reference to a default initialized <code>C</code> object unique to
|
||||||
|
<code>Holder</code>. No invocation of <code>Holder::get()</code>, except possibly
|
||||||
|
the first one in the program, does throw.
|
||||||
|
<a href="flyweight.html#flyweight"><code>flyweight</code></a>
|
||||||
|
privately uses a holder to instantiate a <a href="factories.html#factory">factory</a>
|
||||||
|
and some additional data (like a <a href="locking.html#preliminary">mutex</a> for
|
||||||
|
internal synchronization) unique to each instantiation type of the class template.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A type <code>S</code> is a <i>holder specifier</i> if:
|
||||||
|
<ol>
|
||||||
|
<li>One of the following conditions is satisfied:
|
||||||
|
<ol type="a">
|
||||||
|
<li><a href="#is_holder"><code>is_holder<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>
|
||||||
158
doc/reference/index.html
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Reference</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="lambda_expressions.html">
|
||||||
|
<link rel="up" href="../index.html">
|
||||||
|
<link rel="next" href="../tutorial/lambda_expressions.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Reference</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="../tutorial/lambda_expressions.html"><img src="../prev.gif" alt="annex: MPL lambda expressions" border="0"><br>
|
||||||
|
Annex: MPL lambda expressions
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
|
||||||
|
Index
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="flyweight.html"><img src="../next.gif" alt="flyweight reference" border="0"><br>
|
||||||
|
<code>flyweight</code> reference
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#headers">Header summary</a></li>
|
||||||
|
<li><a href="#flyweight_synopsis">Header
|
||||||
|
<code>"boost/flyweight.hpp"</code> synopsis</a></li>
|
||||||
|
<li><a href="flyweight.html">Class template <code>flyweight</code></a></li>
|
||||||
|
<li><a href="key_value.html">Key-value flyweights</a></li>
|
||||||
|
<li><a href="tags.html">Tags</a></li>
|
||||||
|
<li><a href="factories.html">Factories</a></li>
|
||||||
|
<li><a href="holders.html">Holders</a></li>
|
||||||
|
<li><a href="locking.html">Locking policies</a></li>
|
||||||
|
<li><a href="tracking.html">Tracking policies</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="headers">Header summary</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Boost.Flyweight comprises the following public headers:
|
||||||
|
<ul>
|
||||||
|
<li><a href="#flyweight_synopsis"><code>"boost/flyweight.hpp"</code></a></li>
|
||||||
|
<li>Class template <code>flyweight</code>
|
||||||
|
<ul>
|
||||||
|
<li><a href="flyweight.html#flyweight_fwd_synopsis"><code>"boost/flyweight/flyweight_fwd.hpp"</code></a></li>
|
||||||
|
<li><a href="flyweight.html#synopsis"><code>"boost/flyweight/flyweight.hpp"</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Key-value flyweights
|
||||||
|
<ul>
|
||||||
|
<li><a href="key_value.html#key_value_fwd_synopsis"><code>"boost/flyweight/key_value_fwd.hpp"</code></a></li>
|
||||||
|
<li><a href="key_value.html#synopsis"><code>"boost/flyweight/key_value.hpp"</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Tags
|
||||||
|
<ul>
|
||||||
|
<li><a href="tags.html#tag_synopsis"><code>"boost/flyweight/tag.hpp"</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Factories
|
||||||
|
<ul>
|
||||||
|
<li><a href="factories.html#factory_tag_synopsis"><code>"boost/flyweight/factory_tag.hpp"</code></a></li>
|
||||||
|
<li><a href="factories.html#hashed_factory_fwd_synopsis"><code>"boost/flyweight/hashed_factory_fwd.hpp"</code></a></li>
|
||||||
|
<li><a href="factories.html#hashed_factory_synopsis"><code>"boost/flyweight/hashed_factory.hpp"</code></a></li>
|
||||||
|
<li><a href="factories.html#set_factory_fwd_synopsis"><code>"boost/flyweight/set_factory_fwd.hpp"</code></a></li>
|
||||||
|
<li><a href="factories.html#set_factory_synopsis"><code>"boost/flyweight/set_factory.hpp"</code></a></li>
|
||||||
|
<li><a href="factories.html#assoc_container_factory_fwd_synopsis"><code>"boost/flyweight/assoc_container_factory_fwd.hpp"</code></a></li>
|
||||||
|
<li><a href="factories.html#assoc_container_factory_synopsis"><code>"boost/flyweight/assoc_container_factory.hpp"</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Holders
|
||||||
|
<ul>
|
||||||
|
<li><a href="holders.html#holder_tag_synopsis"><code>"boost/flyweight/holder_tag.hpp"</code></a></li>
|
||||||
|
<li><a href="holders.html#static_holder_fwd_synopsis"><code>"boost/flyweight/static_holder_fwd.hpp"</code></a></li>
|
||||||
|
<li><a href="holders.html#static_holder_synopsis"><code>"boost/flyweight/static_holder.hpp"</code></a></li>
|
||||||
|
<li><a href="holders.html#intermodule_holder_fwd_synopsis"><code>"boost/flyweight/intermodule_holder_fwd.hpp"</code></a></li>
|
||||||
|
<li><a href="holders.html#intermodule_holder_synopsis"><code>"boost/flyweight/intermodule_holder.hpp"</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Locking policies
|
||||||
|
<ul>
|
||||||
|
<li><a href="locking.html#locking_tag_synopsis"><code>"boost/flyweight/locking_tag.hpp"</code></a></li>
|
||||||
|
<li><a href="locking.html#simple_locking_fwd_synopsis"><code>"boost/flyweight/simple_locking_fwd.hpp"</code></a></li>
|
||||||
|
<li><a href="locking.html#simple_locking_synopsis"><code>"boost/flyweight/simple_locking.hpp"</code></a></li>
|
||||||
|
<li><a href="locking.html#no_locking_fwd_synopsis"><code>"boost/flyweight/no_locking_fwd.hpp"</code></a></li>
|
||||||
|
<li><a href="locking.html#no_locking_synopsis"><code>"boost/flyweight/no_locking.hpp"</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Tracking policies
|
||||||
|
<ul>
|
||||||
|
<li><a href="tracking.html#tracking_tag_synopsis"><code>"boost/flyweight/tracking_tag.hpp"</code></a></li>
|
||||||
|
<li><a href="tracking.html#refcounted_fwd_synopsis"><code>"boost/flyweight/refcounted_fwd.hpp"</code></a></li>
|
||||||
|
<li><a href="tracking.html#refcounted_synopsis"><code>"boost/flyweight/refcounted.hpp"</code></a></li>
|
||||||
|
<li><a href="tracking.html#no_tracking_fwd_synopsis"><code>"boost/flyweight/no_tracking_fwd.hpp"</code></a></li>
|
||||||
|
<li><a href="tracking.html#no_tracking_synopsis"><code>"boost/flyweight/no_tracking.hpp"</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Boost.Flyweight is a header-only library, requiring no additional
|
||||||
|
object modules.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<a name="flyweight_synopsis">Header
|
||||||
|
<a href="../../../../boost/flyweight.hpp"><code>"boost/flyweight.hpp"</code></a>
|
||||||
|
synopsis</a>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
<span class=preprocessor>#include</span> <span class=special><</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 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>
|
||||||
124
doc/reference/key_value.html
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Key-value flyweights reference</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="flyweight.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="tags.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Key-value flyweights reference</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="flyweight.html"><img src="../prev.gif" alt="flyweight reference" border="0"><br>
|
||||||
|
<code>flyweight</code> reference
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
|
||||||
|
Boost.Flyweight reference
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="tags.html"><img src="../next.gif" alt="tags" border="0"><br>
|
||||||
|
Tags
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#key_extractor">Key extractors</a></li>
|
||||||
|
<li><a href="#key_value_fwd_synopsis">Header
|
||||||
|
<code>"boost/flyweight/key_value_fwd.hpp"</code> synopsis</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#synopsis">Header
|
||||||
|
<code>"boost/flyweight/key_value.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#key_value_construct">Class template <code>key_value</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="key_extractor">Key extractors</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Let <code>Key</code> be a type with some implicit equivalence relationship
|
||||||
|
and <code>Value</code> a type constructible from <code>Key</code>.
|
||||||
|
A <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"><code>Default
|
||||||
|
Constructible</code></a> type <code>KeyFromValue</code> is said
|
||||||
|
to be a key extractor from <code>Value</code> to <code>Key</code> if
|
||||||
|
<ol>
|
||||||
|
<li><code>kfv(cv)</code> is defined and have type <code>const Key&</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>
|
||||||
287
doc/reference/locking.html
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Locking policies reference</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="factories.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="tracking.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight
|
||||||
|
Locking policies reference</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="holders.html"><img src="../prev.gif" alt="holders" border="0"><br>
|
||||||
|
Holders
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
|
||||||
|
Boost.Flyweight reference
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="tracking.html"><img src="../next.gif" alt="tracking policies" border="0"><br>
|
||||||
|
Tracking policies
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#preliminary">Preliminary concepts</a></li>
|
||||||
|
<li><a href="#locking">Locking policies</a></li>
|
||||||
|
<li><a href="#locking_tag_synopsis">Header
|
||||||
|
<code>"boost/flyweight/locking_tag.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#is_locking">Class template <code>is_locking</code></a></li>
|
||||||
|
<li><a href="#locking_construct">Class template <code>locking</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#simple_locking_fwd_synopsis">Header
|
||||||
|
<code>"boost/flyweight/simple_locking_fwd.hpp"</code> synopsis</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#simple_locking_synopsis">Header
|
||||||
|
<code>"boost/flyweight/simple_locking.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#simple_locking">Class <code>simple_locking</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#no_locking_fwd_synopsis">Header
|
||||||
|
<code>"boost/flyweight/no_locking_fwd.hpp"</code> synopsis</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#no_locking_synopsis">Header
|
||||||
|
<code>"boost/flyweight/no_locking.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#no_locking">Class <code>no_locking</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="preliminary">Preliminary concepts</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A <i>mutex</i> is a type whose objects can be in either of two states, called
|
||||||
|
locked and unlocked, with the property that when a thread A has locked a
|
||||||
|
mutex <code>m</code> and a different thread B tries to lock <code>m</code>,
|
||||||
|
B is blocked until A unlocks <code>m</code>. Additionally, a mutex is said to
|
||||||
|
support <i>recursive locking</i> if a thread can succesfully invoke the locking
|
||||||
|
operation for a mutex already locked by this same thread; in this case, it is
|
||||||
|
required that the thread execute as many unlock operations as lock
|
||||||
|
operations it has performed for the mutex to become effectively unlocked.
|
||||||
|
A <i>scoped lock</i> is a
|
||||||
|
type associated to some mutex type whose objects do the locking/unlocking
|
||||||
|
of a mutex on construction/destruction time.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In the following table, <code>Mutex</code> is a mutex type, <code>m</code>
|
||||||
|
is an object of type <code>Mutex</code>, <code>Lock</code> is a scoped lock
|
||||||
|
associated to <code>Mutex</code> and <code>lk</code> is a value of
|
||||||
|
<code>Lock</code>.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<table cellspacing="0">
|
||||||
|
<caption><b>Mutex and Scoped Lock requirements.</b></caption>
|
||||||
|
<tr>
|
||||||
|
<th align="center">expression</th>
|
||||||
|
<th align="center">return type</th>
|
||||||
|
<th align="center">assertion/note<br>pre/post-condition</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>Mutex m;</code></td>
|
||||||
|
<td> </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/concepts.htm">Boost Thread
|
||||||
|
Library</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2><a name="locking">Locking policies</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<i>Locking policies</i> describe a mutex type and an associated
|
||||||
|
scoped lock type.
|
||||||
|
<a href="flyweight.html#flyweight"><code>flyweight</code></a> uses a given locking
|
||||||
|
policy to synchronize the access to its internal
|
||||||
|
<a href="factories.html#factory">factory</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A type <code>Locking</code> is a locking policy if:
|
||||||
|
<ul>
|
||||||
|
<li>One of the following conditions is satisfied:
|
||||||
|
<ol type="a">
|
||||||
|
<li><a href="#is_locking"><code>is_locking<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="#tracking_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 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>
|
||||||
107
doc/reference/tags.html
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Tags reference</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="key_value.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="factories.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight
|
||||||
|
Tags reference</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="key_value.html"><img src="../prev.gif" alt="key-value flyweights" border="0"><br>
|
||||||
|
Key-value flyweights
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
|
||||||
|
Boost.Flyweight reference
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="factories.html"><img src="../next.gif" alt="factories" border="0"><br>
|
||||||
|
Factories
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#tag">Tags</a></li>
|
||||||
|
<li><a href="#tag_synopsis">Header
|
||||||
|
<code>"boost/flyweight/tag.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#tag_construct">Class template <code>tag</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="tag">Tags</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A <i>tag</i> is a type of the form
|
||||||
|
<a href="#tag_construct"><code>tag<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>
|
||||||
291
doc/reference/tracking.html
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Tracking policies reference</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="locking.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="../performance.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight
|
||||||
|
Tracking policies reference</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="locking.html"><img src="../prev.gif" alt="locking policies" border="0"><br>
|
||||||
|
Locking policies
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight reference" border="0"><br>
|
||||||
|
Boost.Flyweight reference
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="../performance.html"><img src="../next.gif" alt="performance" border="0"><br>
|
||||||
|
Performance
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#preliminary">Preliminary concepts</a></li>
|
||||||
|
<li><a href="#tracking">Tracking policies</a></li>
|
||||||
|
<li><a href="#tracking_tag_synopsis">Header
|
||||||
|
<code>"boost/flyweight/tracking_tag.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#is_tracking">Class template <code>is_tracking</code></a></li>
|
||||||
|
<li><a href="#tracking_construct">Class template <code>tracking</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#refcounted_fwd_synopsis">Header
|
||||||
|
<code>"boost/flyweight/refcounted_fwd.hpp"</code> synopsis</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#refcounted_synopsis">Header
|
||||||
|
<code>"boost/flyweight/refcounted.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#refcounted">Class <code>refcounted</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#no_tracking_fwd_synopsis">Header
|
||||||
|
<code>"boost/flyweight/no_tracking_fwd.hpp"</code> synopsis</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#no_tracking_synopsis">Header
|
||||||
|
<code>"boost/flyweight/no_tracking.hpp"</code> synopsis</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#no_tracking">Class <code>no_tracking</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="preliminary">Preliminary concepts</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A <i>tracking policy helper</i> provides access to some of the functionality
|
||||||
|
of a <a href="factories.html#factory">factory</a> so as to be used
|
||||||
|
in the implementation of an associated <a href="#tracking"><code>Tracking Policy</code></a>.
|
||||||
|
In the following table, <code>TrackingHelper</code> is a tracking policy
|
||||||
|
helper associated to a <a href="factories.html#factory">factory</a> type
|
||||||
|
<code>Factory</code> of elements of type <code>Entry</code>, <code>h</code>
|
||||||
|
is a value of
|
||||||
|
<code>Factory::handle_type</code> associated to a <code>Factory</code> <code>f</code>
|
||||||
|
and <code>check</code> is a value of
|
||||||
|
a <a href="http://www.sgi.com/tech/stl/Predicate.html"><code>Predicate</code></a>
|
||||||
|
type <code>Checker</code> with argument of type <code>Factory::handle_type</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<table cellspacing="0">
|
||||||
|
<caption><b>Tracking Policy Helper requirements.</b></caption>
|
||||||
|
<tr>
|
||||||
|
<th align="center">expression</th>
|
||||||
|
<th align="center">return type</th>
|
||||||
|
<th align="center">assertion/note<br>pre/post-condition</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>TrackingHelper::entry(h);</code></td>
|
||||||
|
<td><code>const Entry&</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>
|
||||||
70
doc/release_notes.html
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Release notes</title>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css">
|
||||||
|
<link rel="start" href="index.html">
|
||||||
|
<link rel="prev" href="future_work.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="acknowledgements.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Release notes</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="future_work.html"><img src="prev.gif" alt="future work" border="0"><br>
|
||||||
|
Future work
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
|
||||||
|
Index
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="acknowledgements.html"><img src="next.gif" alt="acknowledgements" border="0"><br>
|
||||||
|
Acknowledgements
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
<br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#boost_1_38">Boost 1.38 release</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="boost_1_38">Boost 1.38 release</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<ul>
|
||||||
|
<li>Initial release of Boost.Flyweight.</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="future_work.html"><img src="prev.gif" alt="future work" border="0"><br>
|
||||||
|
Future work
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
|
||||||
|
Index
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="acknowledgements.html"><img src="next.gif" alt="acknowledgements" border="0"><br>
|
||||||
|
Acknowledgements
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
<br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p>Revised August 27th 2008</p>
|
||||||
|
|
||||||
|
<p>© 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>
|
||||||
54
doc/style.css
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/* Copyright 2003-2004 Joaquín M López Muñoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre{
|
||||||
|
BORDER-RIGHT: gray 1pt solid;
|
||||||
|
PADDING-RIGHT: 2pt;
|
||||||
|
BORDER-TOP: gray 1pt solid;
|
||||||
|
DISPLAY: block;
|
||||||
|
PADDING-LEFT: 2pt;
|
||||||
|
PADDING-BOTTOM: 2pt;
|
||||||
|
BORDER-LEFT: gray 1pt solid;
|
||||||
|
MARGIN-RIGHT: 32pt;
|
||||||
|
PADDING-TOP: 2pt;
|
||||||
|
BORDER-BOTTOM: gray 1pt solid;
|
||||||
|
FONT-FAMILY: "Courier New", Courier, mono;
|
||||||
|
background-color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
table{
|
||||||
|
PADDING-RIGHT: 2pt;
|
||||||
|
BORDER-TOP: gray 1pt solid;
|
||||||
|
DISPLAY: block;
|
||||||
|
PADDING-LEFT: 2pt;
|
||||||
|
PADDING-BOTTOM: 2pt;
|
||||||
|
BORDER-LEFT: gray 1pt solid;
|
||||||
|
MARGIN-RIGHT: 32pt;
|
||||||
|
PADDING-TOP: 2pt;
|
||||||
|
background-color: #EEEEEE;
|
||||||
|
}
|
||||||
|
td{
|
||||||
|
BORDER-STYLE: solid;
|
||||||
|
BORDER-WIDTH: 1pt;
|
||||||
|
BORDER-LEFT: ;
|
||||||
|
BORDER-RIGHT: gray 1pt solid;
|
||||||
|
BORDER-TOP: ;
|
||||||
|
BORDER-BOTTOM: gray 1pt solid;
|
||||||
|
}
|
||||||
|
th{color: #ffffff; background-color: #000000;}
|
||||||
|
.odd_tr{background-color: #ffffff;}
|
||||||
|
|
||||||
|
.keyword{color: #0000FF;}
|
||||||
|
.identifier{}
|
||||||
|
.comment{font-style: italic; color: #008000;}
|
||||||
|
.special{color: #800040;}
|
||||||
|
.preprocessor{color: #3F007F;}
|
||||||
|
.string{font-style: italic; color: #666666;}
|
||||||
|
.literal{font-style: italic; color: #666666;}
|
||||||
|
|
||||||
|
.prev_link{width: 30%; float: left; text-align: left;}
|
||||||
|
.up_link{width: 39.9%; float: left; text-align: center;}
|
||||||
|
.next_link{width: 30%; float: left; text-align: right;}
|
||||||
114
doc/tests.html
Normal file
@@ -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>
|
||||||
BIN
doc/time_gcc_344.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
doc/time_msvc_80.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
227
doc/tutorial/basics.html
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Tutorial - Basics</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="index.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="key_value.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Tutorial: Basics</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.Flyweight tutorial" border="0"><br>
|
||||||
|
Boost.Flyweight tutorial
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br>
|
||||||
|
Boost.Flyweight tutorial
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="key_value.html"><img src="../next.gif" alt="key-value flyweights" border="0"><br>
|
||||||
|
Key-value flyweights
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#intro">Introduction</a></li>
|
||||||
|
<li><a href="#requirements">Flyweight requirements</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="intro">Introduction</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Suppose we are writing a massive multiplayer online game
|
||||||
|
which has to maintain hundreds of thousands or millions of instances
|
||||||
|
of the following class in memory:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
<span class=keyword>struct</span> <span class=identifier>user_entry</span>
|
||||||
|
<span class=special>{</span>
|
||||||
|
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>first_name</span><span class=special>;</span>
|
||||||
|
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>last_name</span><span class=special>;</span>
|
||||||
|
<span class=keyword>int</span> <span class=identifier>age</span><span class=special>;</span>
|
||||||
|
<span class=special>...</span>
|
||||||
|
<span class=special>};</span>
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In this kind of environments memory resources are precious, so we are seeking
|
||||||
|
ways to make <code>user_entry</code> as compact as possible. Typically, there
|
||||||
|
exists a very high level of repetition of first and last names among
|
||||||
|
the community users, so an obvious optimization consists in moving
|
||||||
|
<code>user_entry::first_name</code> and <code>user_entry::last_name</code>
|
||||||
|
objects to a common repository where duplicates are avoided, and leaving
|
||||||
|
references to these inside <code>user_entry</code>. This is precisely what
|
||||||
|
Boost.Flyweight does in the simplest possible way for the programmer:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
<span class=preprocessor>#include</span> <span class=special><</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>
|
||||||
647
doc/tutorial/configuration.html
Normal file
@@ -0,0 +1,647 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Tutorial - Configuring Boost.Flyweight</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="key_value.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="extension.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Tutorial: Configuring Boost.Flyweight</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="key_value.html"><img src="../prev.gif" alt="key-value flyweights" border="0"><br>
|
||||||
|
Key-value flyweights
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br>
|
||||||
|
Boost.Flyweight tutorial
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="extension.html"><img src="../next.gif" alt="extending Boost.Flyweight" border="0"><br>
|
||||||
|
Extending Boost.Flyweight
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#intro">Configurable aspects of Boost.Flyweight</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#free_order_template">Free-order template parameter interface</a></li>
|
||||||
|
<li><a href="#header_inclusion">Header inclusion</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#tagging">Tagging</a></li>
|
||||||
|
<li><a href="#factories">Factory specification</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#factory_types">Types involved in the configuration of factories</a></li>
|
||||||
|
<li><a href="#hashed_factory"><code>hashed_factory</code></a></li>
|
||||||
|
<li><a href="#set_factory"><code>set_factory</code></a></li>
|
||||||
|
<li><a href="#assoc_container_factory"><code>assoc_container_factory</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#holders">Holder specification</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#static_holder"><code>static_holder</code></a></li>
|
||||||
|
<li><a href="#intermodule_holder"><code>intermodule_holder</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#locking">Locking policies</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#simple_locking"><code>simple_locking</code></a></li>
|
||||||
|
<li><a href="#no_locking"><code>no_locking</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#tracking">Tracking policies</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#refcounted"><code>refcounted</code></a></li>
|
||||||
|
<li><a href="#no_tracking"><code>no_tracking</code></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="intro">Configurable aspects of Boost.Flyweight</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Most of the time, <code>flyweight</code> default configuration is just good
|
||||||
|
enough and the user need not care about further tuning of her <code>flyweight</code>
|
||||||
|
instantiations; however, when the necessity for more control over Boost.Flyweight
|
||||||
|
behavior arises, comprehensive mechanisms are provided to select, configure and
|
||||||
|
even extend the following implementation aspects:
|
||||||
|
<ul>
|
||||||
|
<li><a href="#tagging">Type tagging</a>.</li>
|
||||||
|
<li><a href="#factories">Factory</a> used to store the shared values
|
||||||
|
<code>flyweight</code> objects refer to.
|
||||||
|
</li>
|
||||||
|
<li><a href="#holders">Mechanism of instantiation</a> of the flyweight factory.</li>
|
||||||
|
<li>Internal <a href="#locking">synchronization mechanism</a> for access to
|
||||||
|
the internal factory in multithreaded environments.</li>
|
||||||
|
<li><a href="#tracking">Tracking policy</a> controlling how a value stored in the
|
||||||
|
factory is handled when all the flyweight objects associated to it are
|
||||||
|
destroyed.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3><a name="free_order_template">Free-order template parameter interface</a></h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The <code>flyweight</code> class template features a "smart" specification
|
||||||
|
interface by which the configuration aspects can be provided as optional template arguments
|
||||||
|
in whatever order the user pleases. For instance, a tagged <code>flyweight</code>
|
||||||
|
of <code>std::string</code>s with a <a href="#set_factory">set-based factory</a> and
|
||||||
|
<a href="#no_tracking">no tracking</a> can be specified like this:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
<span class=identifier>flyweight</span><span class=special><</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>
|
||||||
562
doc/tutorial/extension.html
Normal file
@@ -0,0 +1,562 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Tutorial - Extending Boost.Flyweight</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="configuration.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="technical.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Tutorial: Extending Boost.Flyweight</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="configuration.html"><img src="../prev.gif" alt="configuring Boost.Flyweight" border="0"><br>
|
||||||
|
Configuring Boost.Flyweight
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br>
|
||||||
|
Boost.Flyweight tutorial
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="technical.html"><img src="../next.gif" alt="technical issues" border="0"><br>
|
||||||
|
Technical issues
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#intro">Introduction</a></li>
|
||||||
|
<li><a href="#factories">Custom factories</a></li>
|
||||||
|
<li><a href="#holders">Custom holders</a></li>
|
||||||
|
<li><a href="#locking">Custom locking policies</a></li>
|
||||||
|
<li><a href="#tracking">Custom tracking policies</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="intro">Introduction</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Boost.Flyweight provides public interface specifications of
|
||||||
|
its <a href="configuration.html">configurable aspects</a> so that the user
|
||||||
|
can extend the library by implementing her own components and providing them to
|
||||||
|
instantiations of the <code>flyweight</code> class template.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In most cases there are two types of entities involved in extending a given
|
||||||
|
aspect of Boost.Flyweight:
|
||||||
|
<ul>
|
||||||
|
<li>The component itself (for instance, a factory class template).</li>
|
||||||
|
<li>The associated <i>component specifier</i>, which is the type
|
||||||
|
provided as a template argument of a <code>flyweight</code>
|
||||||
|
instantiation.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
For example, the type
|
||||||
|
<a href="configuration.html#static_holder"><code>static_holder</code></a>
|
||||||
|
is a holder specifier which is used by <code>flyweight</code> to generate
|
||||||
|
actual holder classes, in this case instantiations of the class
|
||||||
|
template
|
||||||
|
<a href="../reference/holders.html#static_holder_class"><code>static_holder_class</code></a>.
|
||||||
|
Note that <code>static_holder</code> is a concrete type while
|
||||||
|
<code>static_holder_class</code> is a class template, so a specifier can be
|
||||||
|
seen as a convenient way to provide access to a family of related concrete
|
||||||
|
components (the different possible instantiations of the class template):
|
||||||
|
<code>flyweight</code> internally selects the particular component
|
||||||
|
appropriate for its internal needs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2><a name="factories">Custom factories</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In a way, factories resemble unique associative containers like <code>std::set</code>,
|
||||||
|
though their expected interface is much more concise:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
<span class=comment>// example of a possible factory class template</span>
|
||||||
|
|
||||||
|
<span class=keyword>template</span><span class=special><</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>
|
||||||
BIN
doc/tutorial/flyweight_rep.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
170
doc/tutorial/index.html
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Tutorial</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="../index.html">
|
||||||
|
<link rel="up" href="../index.html">
|
||||||
|
<link rel="next" href="basics.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Tutorial</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="../index.html"><img src="../prev.gif" alt="index" border="0"><br>
|
||||||
|
Index
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
|
||||||
|
Index
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="basics.html"><img src="../next.gif" alt="basics" border="0"><br>
|
||||||
|
Basics
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#rationale">Rationale</a></li>
|
||||||
|
<li><a href="#namespace">Namespace</a></li>
|
||||||
|
<li><a href="#guide">Guide to the reader</a></li>
|
||||||
|
<li><a href="basics.html">Basics</a></li>
|
||||||
|
<li><a href="key_value.html">Key-value flyweights</a></li>
|
||||||
|
<li><a href="configuration.html">Configuring Boost.Flyweight</a></li>
|
||||||
|
<li><a href="extension.html">Extending Boost.Flyweight</a></li>
|
||||||
|
<li><a href="technical.html">Technical issues</a></li>
|
||||||
|
<li><a href="lambda_expressions.html">Annex: MPL Lambda expressions</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="rationale">Rationale</a></h2>
|
||||||
|
|
||||||
|
<span style="float:left;margin-right:20px;margin-bottom:20px">
|
||||||
|
<p align="center">
|
||||||
|
<img src="flyweight_rep.png"
|
||||||
|
alt="representation of a flyweight scenario"
|
||||||
|
width="424" height="320"><br>
|
||||||
|
<b>Fig. 1: Representation of a flyweight scenario.</b>
|
||||||
|
</p>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Consider an application that has to manage large quantities of objects of
|
||||||
|
moderate size, potentially requiring more memory than reasonably available.
|
||||||
|
When these objects are <i>immutable</i>, i.e. they do not modify its internal
|
||||||
|
state except maybe for reattaching to a new set of state data, and some
|
||||||
|
additional conditions are met, a very convenient optimization technique known
|
||||||
|
as the <i>flyweight pattern</i> can be introduced.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Let us say there are <i>N</i> different objects living at a given time
|
||||||
|
inside the application, globally taking <i>M</i> different values. If <i>N</i>
|
||||||
|
is much greater than <i>M</i>, that is, there are many equivalent objects,
|
||||||
|
we can eliminate the implicit redundancy by replacing the original objects with
|
||||||
|
handle classes which refer to a common repository of shared value objects,
|
||||||
|
as depicted in the figure. The handle objects or flyweights, which act as
|
||||||
|
proxies for the actual values, typically occupy the size of a mere pointer.
|
||||||
|
The larger the value classes, and the greater the <i>N</i>/<i>M</i> ratio,
|
||||||
|
the more significant the memory savings achieved by this tecnhique. The
|
||||||
|
classical example of application of the flyweight idiom is that of a word
|
||||||
|
processor: each letter in the document carries a large wealth of
|
||||||
|
information, such as its Unicode identifier, font, size, typesetting effects,
|
||||||
|
etc., but given that the degree of letter repetition in a document is extremely
|
||||||
|
high, implementing those letters as flyweight classes allows us to easily
|
||||||
|
handle documents ranging in the hundreds of thousands of characters.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Most presentations of the design pattern found in the literature do make a
|
||||||
|
distinction between the flyweight <i>intrinsic information</i> (the constant
|
||||||
|
data factored out into the repository) and <i>extrinsic</i>, mutable
|
||||||
|
information, which is stored along with the flyweight objects or passed
|
||||||
|
externally. This separation analysis can have some merit from the point of
|
||||||
|
view of application design, but when it comes to implementation extrinsic
|
||||||
|
information has no impact on the overall flyweight scheme. So,
|
||||||
|
Boost.Flyweight assumes that the type onto which the library operates
|
||||||
|
entirely consists of intrinsic information: this allows for a particularly
|
||||||
|
appealing realization of the idiom in C++ in which
|
||||||
|
<code>flyweight<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>
|
||||||
231
doc/tutorial/key_value.html
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Tutorial - Key-value flyweights</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="basics.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="configuration.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Tutorial: Key-value flyweights</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="basics.html"><img src="../prev.gif" alt="basics" border="0"><br>
|
||||||
|
Basics
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br>
|
||||||
|
Boost.Flyweight tutorial
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="configuration.html"><img src="../next.gif" alt="configuring Boost.Flyweight" border="0"><br>
|
||||||
|
Configuring Boost.Flyweight
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#key_value">Key-value flyweights</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#key_extractor">Key extractors</a></li>
|
||||||
|
<li><a href="#requirements">Type requirements</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="key_value">Key-value flyweights</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Continuing with our online game example, suppose we have a huge class for
|
||||||
|
handling rendering textures:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
<span class=keyword>class</span> <span class=identifier>texture</span>
|
||||||
|
<span class=special>{</span>
|
||||||
|
<span class=keyword>public</span><span class=special>:</span>
|
||||||
|
<span class=identifier>texture</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&</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 the a compilation error similar to this:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
error: 'boost::mpl::assertion_failed' : cannot convert parameter 1 from
|
||||||
|
'boost::mpl::failed ************(__thiscall boost::flyweights::detail::
|
||||||
|
regular_key_value<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 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>
|
||||||
181
doc/tutorial/lambda_expressions.html
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Tutorial - Annex - MPL lambda expressions</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="technical.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="../reference/index.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Tutorial Annex: MPL lambda expressions</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="technical.html"><img src="../prev.gif" alt="technical issues" border="0"><br>
|
||||||
|
Technical issues
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br>
|
||||||
|
Boost.Flyweight tutorial
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="../reference/index.html"><img src="../next.gif" alt="Boost.Flyweight reference" border="0"><br>
|
||||||
|
Boost.Flyweight reference
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>This short introduction to lambda expressions is meant for readers unfamiliar
|
||||||
|
with the <a href="../../../mpl/doc/index.html">Boost MPL Library</a> who
|
||||||
|
want to rapidly acquire a working knowledge of the basic concepts for the purposes
|
||||||
|
of using them in Boost.Flyweight. Please refer to the Boost.MPL documentation
|
||||||
|
for further information beyond these introductory notes.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The specifiers defined by Boost.Flyweight rely heavily on the
|
||||||
|
<a href="../../../mpl/doc/refmanual/lambda-expression.html"><code>Lambda
|
||||||
|
Expression</code></a> concept defined by the
|
||||||
|
<a href="../../../mpl/doc/index.html">Boost MPL Library</a>. A lambda
|
||||||
|
expression can be thought of as a compile-time "type function", an entity (a
|
||||||
|
concrete type, actually) that can be invoked with a list of types and returns
|
||||||
|
some associated type in its turn. Consider for instance an arbitrary class
|
||||||
|
template:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
<span class=keyword>template</span><span class=special><</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>
|
||||||
193
doc/tutorial/technical.html
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Boost.Flyweight Documentation - Tutorial - Technical issues</title>
|
||||||
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||||
|
<link rel="start" href="../index.html">
|
||||||
|
<link rel="prev" href="extension.html">
|
||||||
|
<link rel="up" href="index.html">
|
||||||
|
<link rel="next" href="lambda_expressions.html">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1><img src="../../../../boost.png" alt="Boost logo" align=
|
||||||
|
"middle" width="277" height="86">Boost.Flyweight Tutorial: Technical issues</h1>
|
||||||
|
|
||||||
|
<div class="prev_link"><a href="extension.html"><img src="../prev.gif" alt="extending Boost.Flyweight" border="0"><br>
|
||||||
|
Extending Boost.Flyweight
|
||||||
|
</a></div>
|
||||||
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br>
|
||||||
|
Boost.Flyweight tutorial
|
||||||
|
</a></div>
|
||||||
|
<div class="next_link"><a href="lambda_expressions.html"><img src="../next.gif" alt="annex: MPL lambda expressions" border="0"><br>
|
||||||
|
Annex: MPL lambda expressions
|
||||||
|
</a></div><br clear="all" style="clear: all;">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#static_init">Static data initialization</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="static_init">Static data initialization</a></h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For any given <code>T</code>, the type <code>flyweight<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 at termination time with something
|
||||||
|
like the following:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
Assertion failed: count()==0, file c:\boost\flyweight\refcounted.hpp, line 55
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
What is the problem? Although the type of <code>v</code> involves
|
||||||
|
<code>flyweight<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 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>
|
||||||
BIN
doc/up.gif
Normal file
|
After Width: | Height: | Size: 853 B |
49
example/Jamfile.v2
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Boost.Flyweight examples Jamfile
|
||||||
|
#
|
||||||
|
# Copyright 2006-2008 Joaquín M López Muñoz.
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
#
|
||||||
|
# See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
|
||||||
|
project
|
||||||
|
: requirements
|
||||||
|
<os>LINUX:<threading>multi
|
||||||
|
;
|
||||||
|
|
||||||
|
exe basic
|
||||||
|
: basic.cpp
|
||||||
|
: <include>$(BOOST_ROOT)
|
||||||
|
;
|
||||||
|
|
||||||
|
exe composite
|
||||||
|
: composite.cpp
|
||||||
|
: <include>$(BOOST_ROOT)
|
||||||
|
;
|
||||||
|
|
||||||
|
exe custom_factory
|
||||||
|
: custom_factory.cpp
|
||||||
|
: <include>$(BOOST_ROOT)
|
||||||
|
;
|
||||||
|
|
||||||
|
exe fibonacci
|
||||||
|
: fibonacci.cpp
|
||||||
|
: <include>$(BOOST_ROOT)
|
||||||
|
;
|
||||||
|
|
||||||
|
exe html
|
||||||
|
: html.cpp
|
||||||
|
: <include>$(BOOST_ROOT)
|
||||||
|
;
|
||||||
|
|
||||||
|
exe key_value
|
||||||
|
: key_value.cpp
|
||||||
|
: <include>$(BOOST_ROOT)
|
||||||
|
;
|
||||||
|
|
||||||
|
exe perf
|
||||||
|
: perf.cpp
|
||||||
|
: <include>$(BOOST_ROOT)
|
||||||
|
: release
|
||||||
|
;
|
||||||
152
example/basic.cpp
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/* Boost.Flyweight basic example.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/flyweight.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace boost::flyweights;
|
||||||
|
|
||||||
|
/* Information associated to a given user of some massive system.
|
||||||
|
* first_name and last_name are turned into flyweights to leverage the
|
||||||
|
* implicit redundancy of names within the user community.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct user_entry
|
||||||
|
{
|
||||||
|
flyweight<std::string> first_name;
|
||||||
|
flyweight<std::string> last_name;
|
||||||
|
int age;
|
||||||
|
|
||||||
|
user_entry();
|
||||||
|
user_entry(const char* first_name,const char* last_name,int age);
|
||||||
|
user_entry(const user_entry& x);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* flyweight<std::string> default ctor simply calls the default ctor of
|
||||||
|
* std::string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
user_entry::user_entry()
|
||||||
|
{}
|
||||||
|
|
||||||
|
/* flyweight<std::string> is constructible from a const char* much as
|
||||||
|
* a std::string is.
|
||||||
|
*/
|
||||||
|
|
||||||
|
user_entry::user_entry(const char* f,const char* l,int a):
|
||||||
|
first_name(f),
|
||||||
|
last_name(l),
|
||||||
|
age(a)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/* flyweight's are copyable and assignable --unlike std::string,
|
||||||
|
* copy and assignment of flyweight<std::string>s do not ever throw.
|
||||||
|
*/
|
||||||
|
|
||||||
|
user_entry::user_entry(const user_entry& x):
|
||||||
|
first_name(x.first_name),
|
||||||
|
last_name(x.last_name),
|
||||||
|
age(x.age)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/* flyweight<std::string> has operator==,!=,<,>,<=,>= with the same
|
||||||
|
* semantics as those of std::string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool same_name(const user_entry& user1,const user_entry& user2)
|
||||||
|
{
|
||||||
|
bool b=user1.first_name==user2.first_name &&
|
||||||
|
user1.last_name==user2.last_name;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* operator<< forwards to the std::string overload */
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os,const user_entry& user)
|
||||||
|
{
|
||||||
|
return os<<user.first_name<<" "<<user.last_name<<" "<<user.age;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* operator>> internally uses std::string's operator>> */
|
||||||
|
|
||||||
|
std::istream& operator>>(std::istream& is,user_entry& user)
|
||||||
|
{
|
||||||
|
return is>>user.first_name>>user.last_name>>user.age;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string full_name(const user_entry& user)
|
||||||
|
{
|
||||||
|
std::string full;
|
||||||
|
|
||||||
|
/* get() returns the underlying const std::string& */
|
||||||
|
|
||||||
|
full.reserve(
|
||||||
|
user.first_name.get().size()+user.last_name.get().size()+1);
|
||||||
|
|
||||||
|
/* here, on the other hand, implicit conversion is used */
|
||||||
|
|
||||||
|
full+=user.first_name;
|
||||||
|
full+=" ";
|
||||||
|
full+=user.last_name;
|
||||||
|
|
||||||
|
return full;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* flyweight<std::string> value is immutable, but a flyweight object can
|
||||||
|
* be assigned a different value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void change_name(user_entry& user,const std::string& f,const std::string& l)
|
||||||
|
{
|
||||||
|
user.first_name=f;
|
||||||
|
user.last_name=l;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
/* play a little with a vector of user_entry's */
|
||||||
|
|
||||||
|
std::string users_txt=
|
||||||
|
"olegh smith 31\n"
|
||||||
|
"john brown 28\n"
|
||||||
|
"anna jones 45\n"
|
||||||
|
"maria garcia 30\n"
|
||||||
|
"john fox 56\n"
|
||||||
|
"anna brown 19\n"
|
||||||
|
"thomas smith 46\n"
|
||||||
|
"andrew martin 28";
|
||||||
|
|
||||||
|
std::vector<user_entry> users;
|
||||||
|
std::istringstream iss(users_txt);
|
||||||
|
while(iss){
|
||||||
|
user_entry u;
|
||||||
|
if(iss>>u)users.push_back(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
change_name(users[0],"oleg","smith");
|
||||||
|
|
||||||
|
user_entry anna("anna","jones",20);
|
||||||
|
std::replace_if(
|
||||||
|
users.begin(),users.end(),
|
||||||
|
boost::bind(same_name,_1,anna),
|
||||||
|
anna);
|
||||||
|
|
||||||
|
std::copy(
|
||||||
|
users.begin(),users.end(),
|
||||||
|
std::ostream_iterator<user_entry>(std::cout,"\n"));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
179
example/composite.cpp
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
/* Boost.Flyweight example of a composite design.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/flyweight.hpp>
|
||||||
|
#include <boost/functional/hash.hpp>
|
||||||
|
#include <boost/tokenizer.hpp>
|
||||||
|
#include <boost/variant.hpp>
|
||||||
|
#include <boost/variant/apply_visitor.hpp>
|
||||||
|
#include <boost/variant/recursive_wrapper.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace boost::flyweights;
|
||||||
|
|
||||||
|
/* A node of a lisp-like list can be modeled as a boost::variant of
|
||||||
|
* 1. A string (primitive node)
|
||||||
|
* 2. A vector of nodes (embedded list)
|
||||||
|
* To save space, 2 is stored as a vector of flyweights.
|
||||||
|
* As is usual with recursive data structures, a node can be thought
|
||||||
|
* of also as a list. To close the flyweight circle, the final
|
||||||
|
* type list is a flyweight wrapper, so that the final structure can
|
||||||
|
* be described as follows in BNF-like style:
|
||||||
|
*
|
||||||
|
* list ::= flyweight<list_impl>
|
||||||
|
* list_impl ::= std::string | std::vector<list>
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct list_elems;
|
||||||
|
|
||||||
|
typedef boost::variant<
|
||||||
|
std::string,
|
||||||
|
boost::recursive_wrapper<list_elems>
|
||||||
|
> list_impl;
|
||||||
|
|
||||||
|
struct list_elems:std::vector<flyweight<list_impl> >{};
|
||||||
|
|
||||||
|
typedef flyweight<list_impl> list;
|
||||||
|
|
||||||
|
/* list_impl must be hashable to be used by flyweight: If a
|
||||||
|
* node is a std::string, its hash resolves to that of the string;
|
||||||
|
* if it is a vector of nodes, we compute the hash by combining
|
||||||
|
* the *addresses* of the stored flyweights' associated values: this is
|
||||||
|
* consistent because flyweight equality implies equality of reference.
|
||||||
|
* Using this trick instead of hashing the node values themselves
|
||||||
|
* allow us to do the computation without recursively descending down
|
||||||
|
* through the entire data structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct list_hasher:boost::static_visitor<std::size_t>
|
||||||
|
{
|
||||||
|
std::size_t operator()(const std::string& str)const
|
||||||
|
{
|
||||||
|
boost::hash<std::string> h;
|
||||||
|
return h(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t operator()(
|
||||||
|
const boost::recursive_wrapper<list_elems>& elmsw)const
|
||||||
|
{
|
||||||
|
const list_elems& elms=elmsw.get();
|
||||||
|
std::size_t res=0;
|
||||||
|
for(list_elems::const_iterator it=elms.begin(),it_end=elms.end();
|
||||||
|
it!=it_end;++it){
|
||||||
|
const list_impl* p=&it->get();
|
||||||
|
boost::hash_combine(res,p);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||||
|
namespace boost{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::size_t hash_value(const list_impl& limpl)
|
||||||
|
{
|
||||||
|
return boost::apply_visitor(list_hasher(),limpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||||
|
} /* namespace boost */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* basic pretty printer with indentation according to the nesting level */
|
||||||
|
|
||||||
|
struct list_pretty_printer:boost::static_visitor<>
|
||||||
|
{
|
||||||
|
list_pretty_printer():nest(0){}
|
||||||
|
|
||||||
|
void operator()(const std::string& str)
|
||||||
|
{
|
||||||
|
indent();
|
||||||
|
std::cout<<str<<"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const boost::recursive_wrapper<list_elems>& elmsw)
|
||||||
|
{
|
||||||
|
indent();
|
||||||
|
std::cout<<"(\n";
|
||||||
|
++nest;
|
||||||
|
const list_elems& elms=elmsw.get();
|
||||||
|
for(list_elems::const_iterator it=elms.begin(),it_end=elms.end();
|
||||||
|
it!=it_end;++it){
|
||||||
|
boost::apply_visitor(*this,it->get());
|
||||||
|
}
|
||||||
|
--nest;
|
||||||
|
indent();
|
||||||
|
std::cout<<")\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void indent()const
|
||||||
|
{
|
||||||
|
for(int i=nest;i--;)std::cout<<" ";
|
||||||
|
}
|
||||||
|
|
||||||
|
int nest;
|
||||||
|
};
|
||||||
|
|
||||||
|
void pretty_print(const list& l)
|
||||||
|
{
|
||||||
|
list_pretty_printer pp;
|
||||||
|
boost::apply_visitor(pp,l.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* list parser */
|
||||||
|
|
||||||
|
template<typename InputIterator>
|
||||||
|
list parse_list(InputIterator& first,InputIterator last,int nest)
|
||||||
|
{
|
||||||
|
list_elems elms;
|
||||||
|
while(first!=last){
|
||||||
|
std::string str=*first++;
|
||||||
|
if(str=="("){
|
||||||
|
elms.push_back(parse_list(first,last,nest+1));
|
||||||
|
}
|
||||||
|
else if(str==")"){
|
||||||
|
if(nest==0)throw std::runtime_error("unmatched )");
|
||||||
|
return list(elms);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
elms.push_back(list(str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(nest!=0)throw std::runtime_error("unmatched (");
|
||||||
|
return list(elms);
|
||||||
|
}
|
||||||
|
|
||||||
|
list parse_list(const std::string str)
|
||||||
|
{
|
||||||
|
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||||
|
tokenizer tok(str,boost::char_separator<char>(" ","()"));
|
||||||
|
tokenizer::iterator begin=tok.begin();
|
||||||
|
return parse_list(begin,tok.end(),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout<<"enter list: ";
|
||||||
|
std::string str;
|
||||||
|
std::getline(std::cin,str);
|
||||||
|
try{
|
||||||
|
pretty_print(parse_list(str));
|
||||||
|
}
|
||||||
|
catch(const std::exception& e){
|
||||||
|
std::cout<<"error: "<<e.what()<<"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
122
example/custom_factory.cpp
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/* Boost.Flyweight example of custom factory.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We include the default components of Boost.Flyweight except the factory,
|
||||||
|
* which will be provided by ourselves.
|
||||||
|
*/
|
||||||
|
#include <boost/flyweight/flyweight.hpp>
|
||||||
|
#include <boost/flyweight/factory_tag.hpp>
|
||||||
|
#include <boost/flyweight/static_holder.hpp>
|
||||||
|
#include <boost/flyweight/simple_locking.hpp>
|
||||||
|
#include <boost/flyweight/refcounted.hpp>
|
||||||
|
#include <boost/tokenizer.hpp>
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
using namespace boost::flyweights;
|
||||||
|
|
||||||
|
/* custom factory based on std::set with some logging capabilities */
|
||||||
|
|
||||||
|
/* Entry is the type of the stored objects. Value is the type
|
||||||
|
* on which flyweight operates, that is, the T in flyweoght<T>. It
|
||||||
|
* is guaranteed that Entry implicitly converts to const Value&.
|
||||||
|
* The factory class could accept other template arguments (for
|
||||||
|
* instance, a comparison predicate for the values), we leave it like
|
||||||
|
* that for simplicity.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename Entry,typename Key>
|
||||||
|
class verbose_factory_class
|
||||||
|
{
|
||||||
|
/* Entry store. Since Entry is implicitly convertible to const Key&,
|
||||||
|
* we can directly use std::less<Key> as the comparer for std::set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef std::set<Entry,std::less<Key> > store_type;
|
||||||
|
|
||||||
|
store_type store;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename store_type::iterator handle_type;
|
||||||
|
|
||||||
|
handle_type insert(const Entry& x)
|
||||||
|
{
|
||||||
|
/* locate equivalent entry or insert otherwise */
|
||||||
|
|
||||||
|
std::pair<handle_type, bool> p=store.insert(x);
|
||||||
|
if(p.second){ /* new entry */
|
||||||
|
std::cout<<"new: "<<(const Key&)x<<std::endl;
|
||||||
|
}
|
||||||
|
else{ /* existing entry */
|
||||||
|
std::cout<<"hit: "<<(const Key&)x<<std::endl;
|
||||||
|
}
|
||||||
|
return p.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase(handle_type h)
|
||||||
|
{
|
||||||
|
std::cout<<"del: "<<(const Key&)*h<<std::endl;
|
||||||
|
store.erase(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Entry& entry(handle_type h)
|
||||||
|
{
|
||||||
|
return *h; /* handle_type is an iterator */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Specifier for verbose_factory_class. The simplest way to tag
|
||||||
|
* this struct as a factory specifier, so that flyweight<> accepts it
|
||||||
|
* as such, is by deriving from boost::flyweights::factory_marker.
|
||||||
|
* See the documentation for info on alternative tagging methods.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct verbose_factory: factory_marker
|
||||||
|
{
|
||||||
|
template<typename Entry,typename Key>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef verbose_factory_class<Entry,Key> type;
|
||||||
|
} ;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ready to use it */
|
||||||
|
|
||||||
|
typedef flyweight<std::string,verbose_factory> fw_string;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
|
||||||
|
|
||||||
|
|
||||||
|
std::string text=
|
||||||
|
"I celebrate myself, and sing myself, "
|
||||||
|
"And what I assume you shall assume, "
|
||||||
|
"For every atom belonging to me as good belongs to you. "
|
||||||
|
|
||||||
|
"I loafe and invite my soul, "
|
||||||
|
"I lean and loafe at my ease observing a spear of summer grass. "
|
||||||
|
|
||||||
|
"My tongue, every atom of my blood, form'd from this soil, this air, "
|
||||||
|
"Born here of parents born here from parents the same, and their "
|
||||||
|
" parents the same, "
|
||||||
|
"I, now thirty-seven years old in perfect health begin, "
|
||||||
|
"Hoping to cease not till death.";
|
||||||
|
|
||||||
|
std::vector<fw_string> v;
|
||||||
|
|
||||||
|
text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
|
||||||
|
for(text_tokenizer::iterator it=tok.begin();it!=tok.end();){
|
||||||
|
v.push_back(fw_string(*it++));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
58
example/fibonacci.cpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/* Boost.Flyweight example of flyweight-based memoization.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/flyweight.hpp>
|
||||||
|
#include <boost/flyweight/key_value.hpp>
|
||||||
|
#include <boost/flyweight/no_tracking.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace boost::flyweights;
|
||||||
|
|
||||||
|
/* Memoized calculation of Fibonacci numbers */
|
||||||
|
|
||||||
|
/* This class takes an int n and calculates F(n) at construction time */
|
||||||
|
|
||||||
|
struct compute_fibonacci;
|
||||||
|
|
||||||
|
/* A Fibonacci number can be modeled as a key-value flyweight
|
||||||
|
* We choose the no_tracking policy so that the calculations
|
||||||
|
* persist for future use throughout the program. See
|
||||||
|
* Tutorial: Configuring Boost.Flyweight: Tracking policies for
|
||||||
|
* further information on tracking policies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef flyweight<key_value<int,compute_fibonacci>,no_tracking> fibonacci;
|
||||||
|
|
||||||
|
/* Implementation of compute_fibonacci. Note that the construction
|
||||||
|
* of compute_fibonacci(n) uses fibonacci(n-1) and fibonacci(n-2),
|
||||||
|
* which effectively memoizes the computation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct compute_fibonacci:private boost::noncopyable
|
||||||
|
{
|
||||||
|
compute_fibonacci(int n):
|
||||||
|
result(n==0?0:n==1?1:fibonacci(n-2).get()+fibonacci(n-1).get())
|
||||||
|
{}
|
||||||
|
|
||||||
|
operator int()const{return result;}
|
||||||
|
int result;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
/* list some Fibonacci numbers */
|
||||||
|
|
||||||
|
for(int n=0;n<40;++n){
|
||||||
|
std::cout<<"F("<<n<<")="<<fibonacci(n)<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
343
example/html.cpp
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
/* Boost.Flyweight example of flyweight-based formatted text processing.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/flyweight.hpp>
|
||||||
|
#include <boost/functional/hash.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_STDC_NAMESPACE)
|
||||||
|
namespace std{using ::exit;using ::tolower;}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace boost::flyweights;
|
||||||
|
|
||||||
|
/* See the portability section of Boost.Hash at
|
||||||
|
* http://boost.org/doc/html/hash/portability.html
|
||||||
|
* for an explanation of the ADL-related workarounds.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||||
|
namespace flyweights{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* We hash the various flyweight types used in the program hashing
|
||||||
|
* a *pointer* to their contents: this is consistent as equality of
|
||||||
|
* flyweights implies equality of references.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::size_t hash_value(const flyweight<T>& x)
|
||||||
|
{
|
||||||
|
boost::hash<const T*> h;
|
||||||
|
return h(&x.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||||
|
} /* namespace flyweights */
|
||||||
|
#endif
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
/* An HTML tag consists of a name and optional properties of the form
|
||||||
|
* name1=value1 ... namen=valuen. We do not need to parse the properties
|
||||||
|
* for the purposes of the program, hence they are all stored in
|
||||||
|
* html_tag_data::properties in raw form.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct html_tag_data
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const html_tag_data& x,const html_tag_data& y)
|
||||||
|
{
|
||||||
|
return x.name==y.name&&x.properties==y.properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||||
|
namespace boost{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::size_t hash_value(const html_tag_data& x)
|
||||||
|
{
|
||||||
|
std::size_t res=0;
|
||||||
|
boost::hash_combine(res,x.name);
|
||||||
|
boost::hash_combine(res,x.properties);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||||
|
} /* namespace boost */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef flyweight<html_tag_data> html_tag;
|
||||||
|
|
||||||
|
/* parse_tag is passed an iterator positioned at the first char of
|
||||||
|
* the tag after the opening '<' and returns, if succesful, a parsed tag
|
||||||
|
* and whether it is opening (<xx>) or closing (</xx>).
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum tag_type{opening,closing,failure};
|
||||||
|
|
||||||
|
struct parse_tag_res
|
||||||
|
{
|
||||||
|
parse_tag_res(tag_type type_,const html_tag_data& tag_=html_tag_data()):
|
||||||
|
type(type_),tag(tag_){}
|
||||||
|
parse_tag_res(const parse_tag_res& x):type(x.type),tag(x.tag){}
|
||||||
|
|
||||||
|
tag_type type;
|
||||||
|
html_tag tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ForwardIterator>
|
||||||
|
parse_tag_res parse_tag(ForwardIterator& first,ForwardIterator last)
|
||||||
|
{
|
||||||
|
html_tag_data tag;
|
||||||
|
std::string buf;
|
||||||
|
bool in_quote=false;
|
||||||
|
for(ForwardIterator it=first;it!=last;){
|
||||||
|
char ch=*it++;
|
||||||
|
if(ch=='>'&&!in_quote){ /* ignore '>'s if inside quotes */
|
||||||
|
tag_type type;
|
||||||
|
std::string::size_type
|
||||||
|
bname=buf.find_first_not_of("\t\n\r "),
|
||||||
|
ename=bname==std::string::npos?
|
||||||
|
std::string::npos:
|
||||||
|
buf.find_first_of("\t\n\r ",bname),
|
||||||
|
bprop=ename==std::string::npos?
|
||||||
|
std::string::npos:
|
||||||
|
buf.find_first_not_of("\t\n\r ",ename);
|
||||||
|
if(bname==ename){ /* null name */
|
||||||
|
return parse_tag_res(failure);
|
||||||
|
}
|
||||||
|
else if(buf[bname]=='/'){ /* closing tag */
|
||||||
|
type=closing;
|
||||||
|
++bname;
|
||||||
|
}
|
||||||
|
else type=opening;
|
||||||
|
tag.name=buf.substr(bname,ename-bname);
|
||||||
|
std::transform( /* normalize tag name to lower case */
|
||||||
|
tag.name.begin(),tag.name.end(),tag.name.begin(),
|
||||||
|
(int(*)(int))std::tolower);
|
||||||
|
if(bprop!=std::string::npos){
|
||||||
|
tag.properties=buf.substr(bprop,buf.size());
|
||||||
|
}
|
||||||
|
first=it; /* result good, consume the chars */
|
||||||
|
return parse_tag_res(type,tag);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(ch=='"')in_quote=!in_quote;
|
||||||
|
buf+=ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parse_tag_res(failure); /* end reached and found no '>' */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A character context is just a vector containing the tags enclosing the
|
||||||
|
* character, from the outermost level to the innermost.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef std::vector<html_tag> html_context_data;
|
||||||
|
typedef flyweight<html_context_data> html_context;
|
||||||
|
|
||||||
|
/* A character is a char code plus its context.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct character_data
|
||||||
|
{
|
||||||
|
character_data(char code_=0,html_context context_=html_context()):
|
||||||
|
code(code_),context(context_){}
|
||||||
|
character_data(const character_data& x):code(x.code),context(x.context){}
|
||||||
|
|
||||||
|
char code;
|
||||||
|
html_context context;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const character_data& x,const character_data& y)
|
||||||
|
{
|
||||||
|
return x.code==y.code&&x.context==y.context;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||||
|
namespace boost{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::size_t hash_value(const character_data& x)
|
||||||
|
{
|
||||||
|
std::size_t res=0;
|
||||||
|
boost::hash_combine(res,x.code);
|
||||||
|
boost::hash_combine(res,x.context);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||||
|
} /* namespace boost */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef flyweight<character_data> character;
|
||||||
|
|
||||||
|
/* scan_html converts HTML code into a stream of contextualized characters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename ForwardIterator,typename OutputIterator>
|
||||||
|
void scan_html(ForwardIterator first,ForwardIterator last,OutputIterator out)
|
||||||
|
{
|
||||||
|
html_context_data context;
|
||||||
|
while(first!=last){
|
||||||
|
if(*first=='<'){ /* tag found */
|
||||||
|
++first;
|
||||||
|
parse_tag_res res=parse_tag(first,last);
|
||||||
|
if(res.type==opening){ /* add to contex */
|
||||||
|
context.push_back(res.tag);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(res.type==closing){ /* remove from context */
|
||||||
|
/* Pop all tags from the innermost to the matching one; this takes
|
||||||
|
* care of missing </xx>s like vg. in <ul><li>hello</ul>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for(html_context_data::reverse_iterator rit=context.rbegin();
|
||||||
|
rit!=context.rend();++rit){
|
||||||
|
if(rit->get().name==res.tag.get().name){
|
||||||
|
context.erase(rit.base()-1,context.end());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out++=character(*first++,html_context(context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HTML-producing utilities */
|
||||||
|
|
||||||
|
void print_opening_tag(std::ostream& os,const html_tag_data& x)
|
||||||
|
{
|
||||||
|
os<<"<"<<x.name;
|
||||||
|
if(!x.properties.empty())os<<" "<<x.properties;
|
||||||
|
os<<">";
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_closing_tag(std::ostream& os,const html_tag_data& x)
|
||||||
|
{
|
||||||
|
/* SGML declarations (beginning with '!') are not closed */
|
||||||
|
|
||||||
|
if(x.name[0]!='!')os<<"</"<<x.name<<">";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* change_context takes contexts from and to with tags
|
||||||
|
*
|
||||||
|
* from<- c1 ... cn fn+1 ... fm
|
||||||
|
* to <- c1 ... cn tn+1 ... tk
|
||||||
|
*
|
||||||
|
* (that is, they share the first n tags, n might be 0), and
|
||||||
|
* produces code closing fm ... fn+1 and opening tn+1 ... tk.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename OutputIterator>
|
||||||
|
void change_context(
|
||||||
|
const html_context_data& from,const html_context_data& to,
|
||||||
|
OutputIterator out)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
html_context_data::const_iterator
|
||||||
|
it0=from.begin(),
|
||||||
|
it0_end=from.end(),
|
||||||
|
it1=to.begin(),
|
||||||
|
it1_end=to.end();
|
||||||
|
for(;it0!=it0_end&&it1!=it1_end&&*it0==*it1;++it0,++it1);
|
||||||
|
while(it0_end!=it0)print_closing_tag(oss,*--it0_end);
|
||||||
|
while(it1!=it1_end)print_opening_tag(oss,*it1++);
|
||||||
|
std::string str=oss.str();
|
||||||
|
std::copy(str.begin(),str.end(),out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* produce_html is passed a bunch of contextualized characters and emits
|
||||||
|
* the corresponding HTML. The algorithm is simple: tags are opened and closed
|
||||||
|
* as a result of the context from one character to the following changing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename ForwardIterator,typename OutputIterator>
|
||||||
|
void produce_html(ForwardIterator first,ForwardIterator last,OutputIterator out)
|
||||||
|
{
|
||||||
|
html_context context;
|
||||||
|
while(first!=last){
|
||||||
|
if(first->get().context!=context){
|
||||||
|
change_context(context,first->get().context,out);
|
||||||
|
context=first->get().context;
|
||||||
|
}
|
||||||
|
*out++=(first++)->get().code;
|
||||||
|
}
|
||||||
|
change_context(context,html_context(),out); /* close remaining context */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Without these explicit instantiations, MSVC++ 6.5/7.0 does not
|
||||||
|
* find some friend operators in certain contexts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
character dummy1;
|
||||||
|
html_tag dummy2;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout<<"input html file: ";
|
||||||
|
std::string in;
|
||||||
|
std::getline(std::cin,in);
|
||||||
|
std::ifstream ifs(in.c_str());
|
||||||
|
if(!ifs){
|
||||||
|
std::cout<<"can't open "<<in<<std::endl;
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
typedef std::istreambuf_iterator<char> istrbuf_iterator;
|
||||||
|
std::vector<char> html_source;
|
||||||
|
std::copy(
|
||||||
|
istrbuf_iterator(ifs),istrbuf_iterator(),
|
||||||
|
std::back_inserter(html_source));
|
||||||
|
|
||||||
|
/* parse the HTML */
|
||||||
|
|
||||||
|
std::vector<character> scanned_html;
|
||||||
|
scan_html(
|
||||||
|
html_source.begin(),html_source.end(),std::back_inserter(scanned_html));
|
||||||
|
|
||||||
|
/* Now that we have the text as a vector of contextualized characters,
|
||||||
|
* we can shuffle it around and manipulate in almost any way we please.
|
||||||
|
* For instance, the following reverses the central portion of the doc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::reverse(
|
||||||
|
scanned_html.begin()+scanned_html.size()/4,
|
||||||
|
scanned_html.begin()+3*(scanned_html.size()/4));
|
||||||
|
|
||||||
|
/* emit the resulting HTML */
|
||||||
|
|
||||||
|
std::cout<<"output html file: ";
|
||||||
|
std::string out;
|
||||||
|
std::getline(std::cin,out);
|
||||||
|
std::ofstream ofs(out.c_str());
|
||||||
|
if(!ofs){
|
||||||
|
std::cout<<"can't open "<<out<<std::endl;
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
typedef std::ostreambuf_iterator<char> ostrbuf_iterator;
|
||||||
|
produce_html(scanned_html.begin(),scanned_html.end(),ostrbuf_iterator(ofs));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
99
example/key_value.cpp
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/* Boost.Flyweight example of use of key-value flyweights.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/array.hpp>
|
||||||
|
#include <boost/flyweight.hpp>
|
||||||
|
#include <boost/flyweight/key_value.hpp>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace boost::flyweights;
|
||||||
|
|
||||||
|
/* A class simulating a texture resource loaded from file */
|
||||||
|
|
||||||
|
class texture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
texture(const std::string& filename):filename(filename)
|
||||||
|
{
|
||||||
|
std::cout<<"loaded "<<filename<<" file"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture(const texture& x):filename(x.filename)
|
||||||
|
{
|
||||||
|
std::cout<<"texture["<<filename<<"] copied"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
~texture()
|
||||||
|
{
|
||||||
|
std::cout<<"unloaded "<<filename<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& get_filename()const{return filename;}
|
||||||
|
|
||||||
|
// rest of the interface
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* key extractor of filename strings from textures */
|
||||||
|
|
||||||
|
struct texture_filename_extractor
|
||||||
|
{
|
||||||
|
const std::string& operator()(const texture& x)const
|
||||||
|
{
|
||||||
|
return x.get_filename();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* texture flyweight */
|
||||||
|
|
||||||
|
typedef flyweight<
|
||||||
|
key_value<std::string,texture,texture_filename_extractor>
|
||||||
|
> texture_flyweight;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
/* texture filenames */
|
||||||
|
|
||||||
|
const char* texture_filenames[]={
|
||||||
|
"grass.texture","sand.texture","water.texture","wood.texture",
|
||||||
|
"granite.texture","cotton.texture","concrete.texture","carpet.texture"
|
||||||
|
};
|
||||||
|
const int num_texture_filenames=
|
||||||
|
sizeof(texture_filenames)/sizeof(texture_filenames[0]);
|
||||||
|
|
||||||
|
/* create a massive vector of textures */
|
||||||
|
|
||||||
|
std::cout<<"creating flyweights...\n"<<std::endl;
|
||||||
|
|
||||||
|
std::vector<texture_flyweight> textures;
|
||||||
|
for(int i=0;i<50000;++i){
|
||||||
|
textures.push_back(
|
||||||
|
texture_flyweight(texture_filenames[std::rand()%num_texture_filenames]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just for the sake of making use of the key extractor,
|
||||||
|
* assign some flyweights with texture objects rather than strings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for(int j=0;j<50000;++j){
|
||||||
|
textures.push_back(
|
||||||
|
texture_flyweight(
|
||||||
|
textures[std::rand()%textures.size()].get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout<<"\n"<<textures.size()<<" flyweights created\n"<<std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
312
example/perf.cpp
Normal file
@@ -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;
|
||||||
|
}
|
||||||
22
include/boost/flyweight.hpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/flyweight/flyweight.hpp>
|
||||||
|
#include <boost/flyweight/hashed_factory.hpp>
|
||||||
|
#include <boost/flyweight/refcounted.hpp>
|
||||||
|
#include <boost/flyweight/simple_locking.hpp>
|
||||||
|
#include <boost/flyweight/static_holder.hpp>
|
||||||
|
|
||||||
|
#endif
|
||||||
88
include/boost/flyweight/assoc_container_factory.hpp
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_ASSOC_CONTAINER_FACTORY_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_ASSOC_CONTAINER_FACTORY_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/assoc_container_factory_fwd.hpp>
|
||||||
|
#include <boost/flyweight/factory_tag.hpp>
|
||||||
|
#include <boost/mpl/apply.hpp>
|
||||||
|
#include <boost/mpl/aux_/lambda_support.hpp>
|
||||||
|
|
||||||
|
/* Factory class using a given associative container.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
template<typename Container>
|
||||||
|
class assoc_container_factory_class:public factory_marker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename Container::iterator handle_type;
|
||||||
|
typedef typename Container::value_type entry_type;
|
||||||
|
|
||||||
|
handle_type insert(const entry_type& x)
|
||||||
|
{
|
||||||
|
return cont.insert(x).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase(handle_type h)
|
||||||
|
{
|
||||||
|
cont.erase(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const entry_type& entry(handle_type h){return *h;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Container cont;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef assoc_container_factory_class type;
|
||||||
|
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,assoc_container_factory_class,(Container))
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||||
|
/* This is preferred to deriving from factory_marker since checking for
|
||||||
|
* derivation forces the instantiation of the specifier, which is not
|
||||||
|
* needed when the specifier is a placeholder expression.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename Container>
|
||||||
|
struct is_factory<assoc_container_factory_class<Container> >:
|
||||||
|
boost::mpl::true_{};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* assoc_container_factory_class specifier */
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename ContainerSpecifier
|
||||||
|
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION_DEF
|
||||||
|
>
|
||||||
|
struct assoc_container_factory:factory_marker
|
||||||
|
{
|
||||||
|
template<typename Entry,typename Key>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef assoc_container_factory_class<
|
||||||
|
typename mpl::apply2<ContainerSpecifier,Entry,Key>::type
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
35
include/boost/flyweight/assoc_container_factory_fwd.hpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_ASSOC_CONTAINER_FACTORY_FWD_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_ASSOC_CONTAINER_FACTORY_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/flyweight/detail/not_placeholder_expr.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
template<typename Container>
|
||||||
|
class assoc_container_factory_class;
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename ContainerSpecifier
|
||||||
|
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION
|
||||||
|
>
|
||||||
|
struct assoc_container_factory;
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
58
include/boost/flyweight/detail/default_value_policy.hpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_DETAIL_DEFAULT_VALUE_POLICY_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_DETAIL_DEFAULT_VALUE_POLICY_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/flyweight/detail/value_tag.hpp>
|
||||||
|
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||||
|
|
||||||
|
/* Default value policy: the key is the same as the value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
template<typename Value>
|
||||||
|
struct default_value_policy:value_marker
|
||||||
|
{
|
||||||
|
typedef Value key_type;
|
||||||
|
typedef Value value_type;
|
||||||
|
|
||||||
|
struct rep_type
|
||||||
|
{
|
||||||
|
/* template ctors */
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit rep_type
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
|
||||||
|
:x(BOOST_PP_ENUM_PARAMS(n,t)){}
|
||||||
|
#include <boost/flyweight/detail/perfect_fwd.hpp>
|
||||||
|
|
||||||
|
operator const value_type&()const{return x;}
|
||||||
|
|
||||||
|
value_type x;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void construct_value(const rep_type&){}
|
||||||
|
static void copy_value(const rep_type&){}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
75
include/boost/flyweight/detail/dyn_perfect_fwd.hpp
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* no include guards */
|
||||||
|
|
||||||
|
#include <boost/preprocessor/arithmetic/add.hpp>
|
||||||
|
#include <boost/preprocessor/cat.hpp>
|
||||||
|
#include <boost/preprocessor/repetition/enum.hpp>
|
||||||
|
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||||
|
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||||
|
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||||
|
#include <boost/preprocessor/seq/elem.hpp>
|
||||||
|
#include <boost/preprocessor/seq/for_each_product.hpp>
|
||||||
|
#include <boost/preprocessor/seq/size.hpp>
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_CONST(b) BOOST_PP_CAT(BOOST_FLYWEIGHT_CONST,b)
|
||||||
|
#define BOOST_FLYWEIGHT_CONST0
|
||||||
|
#define BOOST_FLYWEIGHT_CONST1 const
|
||||||
|
|
||||||
|
/* if mask[n]==0 --> Tn& tn
|
||||||
|
* if mask[n]==1 --> const Tn& tn
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_ARG(z,n,mask) \
|
||||||
|
BOOST_FLYWEIGHT_CONST(BOOST_PP_SEQ_ELEM(n,mask)) \
|
||||||
|
BOOST_PP_CAT(T,n)& BOOST_PP_CAT(t,n)
|
||||||
|
|
||||||
|
/* overload accepting size(mask) args, where the template args are
|
||||||
|
* marked const or not according to the given mask (a seq of 0 or 1)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD(r,mask) \
|
||||||
|
template<BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(mask),typename T)> \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWD_NAME( \
|
||||||
|
BOOST_PP_ENUM( \
|
||||||
|
BOOST_PP_SEQ_SIZE(mask),BOOST_FLYWEIGHT_PERFECT_FWD_ARG,mask)) \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWD_BODY(BOOST_PP_SEQ_SIZE(mask))
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_01(z,n,_) ((0)(1))
|
||||||
|
|
||||||
|
/* Perfect forwarding overloads accepting 1 to n args */
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWDS_N(z,n,_) \
|
||||||
|
BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWD, \
|
||||||
|
BOOST_PP_REPEAT(n,BOOST_FLYWEIGHT_01,~))
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
|
||||||
|
BOOST_PP_REPEAT_FROM_TO( \
|
||||||
|
1,BOOST_PP_ADD(BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS,1), \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_N,~)
|
||||||
|
|
||||||
|
/* generate the overloads */
|
||||||
|
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS
|
||||||
|
|
||||||
|
/* clean up */
|
||||||
|
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS
|
||||||
|
#undef BOOST_FLYWEIGHT_01
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWD
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWD_ARG
|
||||||
|
#undef BOOST_FLYWEIGHT_CONST1
|
||||||
|
#undef BOOST_FLYWEIGHT_CONST0
|
||||||
|
#undef BOOST_FLYWEIGHT_CONST
|
||||||
|
|
||||||
|
/* user supplied argument macros */
|
||||||
|
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWD_BODY
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWD_NAME
|
||||||
256
include/boost/flyweight/detail/flyweight_core.hpp
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_DETAIL_FLYWEIGHT_CORE_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_DETAIL_FLYWEIGHT_CORE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/detail/no_exceptions_support.hpp>
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
#include <boost/flyweight/detail/handle_factory_adaptor.hpp>
|
||||||
|
#include <boost/mpl/apply.hpp>
|
||||||
|
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4101) /* unreferenced local vars */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* flyweight_core provides the inner implementation of flyweight<> by
|
||||||
|
* weaving together a value policy, a flyweight factory, a holder for the
|
||||||
|
* factory,a tracking policy and a locking policy.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename ValuePolicy,typename Tag,typename TrackingPolicy,
|
||||||
|
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
|
||||||
|
>
|
||||||
|
class flyweight_core;
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename ValuePolicy,typename Tag,typename TrackingPolicy,
|
||||||
|
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
|
||||||
|
>
|
||||||
|
struct flyweight_core_tracking_helper
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef flyweight_core<
|
||||||
|
ValuePolicy,Tag,TrackingPolicy,
|
||||||
|
FactorySpecifier,LockingPolicy,
|
||||||
|
HolderSpecifier
|
||||||
|
> core;
|
||||||
|
typedef typename core::handle_type handle_type;
|
||||||
|
typedef typename core::entry_type entry_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const entry_type& entry(const handle_type& h)
|
||||||
|
{
|
||||||
|
return core::entry(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Checker>
|
||||||
|
static void erase(const handle_type& h,Checker check)
|
||||||
|
{
|
||||||
|
typedef typename core::lock_type lock_type;
|
||||||
|
lock_type lock(core::mutex());
|
||||||
|
if(check(h))core::factory().erase(h);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename ValuePolicy,typename Tag,typename TrackingPolicy,
|
||||||
|
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
|
||||||
|
>
|
||||||
|
class flyweight_core
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename ValuePolicy::key_type key_type;
|
||||||
|
typedef typename ValuePolicy::value_type value_type;
|
||||||
|
typedef typename ValuePolicy::rep_type rep_type;
|
||||||
|
typedef typename mpl::apply2<
|
||||||
|
typename TrackingPolicy::entry_type,
|
||||||
|
rep_type,
|
||||||
|
key_type
|
||||||
|
>::type entry_type;
|
||||||
|
typedef typename mpl::apply2<
|
||||||
|
FactorySpecifier,
|
||||||
|
entry_type,
|
||||||
|
key_type
|
||||||
|
>::type base_factory_type;
|
||||||
|
typedef typename mpl::apply2<
|
||||||
|
typename TrackingPolicy::handle_type,
|
||||||
|
typename base_factory_type::handle_type,
|
||||||
|
flyweight_core_tracking_helper<
|
||||||
|
ValuePolicy,Tag,TrackingPolicy,
|
||||||
|
FactorySpecifier,LockingPolicy,
|
||||||
|
HolderSpecifier
|
||||||
|
>
|
||||||
|
>::type handle_type;
|
||||||
|
typedef handle_factory_adaptor<
|
||||||
|
base_factory_type,
|
||||||
|
handle_type,entry_type
|
||||||
|
> factory_type;
|
||||||
|
typedef typename LockingPolicy::mutex_type mutex_type;
|
||||||
|
typedef typename LockingPolicy::lock_type lock_type;
|
||||||
|
|
||||||
|
static bool init()
|
||||||
|
{
|
||||||
|
if(static_initializer)return true;
|
||||||
|
else{
|
||||||
|
holder_arg& a=holder_type::get();
|
||||||
|
static_factory_ptr=&a.factory;
|
||||||
|
static_mutex_ptr=&a.mutex;
|
||||||
|
static_initializer=(static_factory_ptr!=0);
|
||||||
|
return static_initializer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* insert overloads*/
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_NAME static handle_type insert
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
|
||||||
|
{ \
|
||||||
|
return insert_rep(rep_type(BOOST_PP_ENUM_PARAMS(n,t))); \
|
||||||
|
}
|
||||||
|
#include <boost/flyweight/detail/perfect_fwd.hpp>
|
||||||
|
|
||||||
|
static handle_type insert(const value_type& x){return insert_value(x);}
|
||||||
|
static handle_type insert(value_type& x){return insert_value(x);}
|
||||||
|
|
||||||
|
static const entry_type& entry(const handle_type& h)
|
||||||
|
{
|
||||||
|
return factory().entry(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const value_type& value(const handle_type& h)
|
||||||
|
{
|
||||||
|
return static_cast<const rep_type&>(entry(h));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const key_type& key(const handle_type& h)
|
||||||
|
{
|
||||||
|
return static_cast<const rep_type&>(entry(h));
|
||||||
|
}
|
||||||
|
|
||||||
|
static factory_type& factory()
|
||||||
|
{
|
||||||
|
return *static_factory_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mutex_type& mutex()
|
||||||
|
{
|
||||||
|
return *static_mutex_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct holder_arg
|
||||||
|
{
|
||||||
|
factory_type factory;
|
||||||
|
mutex_type mutex;
|
||||||
|
};
|
||||||
|
typedef typename mpl::apply1<
|
||||||
|
HolderSpecifier,
|
||||||
|
holder_arg
|
||||||
|
>::type holder_type;
|
||||||
|
|
||||||
|
static handle_type insert_rep(const rep_type& x)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
entry_type e(x);
|
||||||
|
lock_type lock(mutex());
|
||||||
|
handle_type h(factory().insert(e));
|
||||||
|
BOOST_TRY{
|
||||||
|
ValuePolicy::construct_value(
|
||||||
|
static_cast<const rep_type&>(entry(h)));
|
||||||
|
}
|
||||||
|
BOOST_CATCH(...){
|
||||||
|
factory().erase(h);
|
||||||
|
BOOST_RETHROW;
|
||||||
|
}
|
||||||
|
BOOST_CATCH_END
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle_type insert_value(const value_type& x)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
entry_type e=entry_type(rep_type(x));
|
||||||
|
lock_type lock(mutex());
|
||||||
|
handle_type h(factory().insert(e));
|
||||||
|
BOOST_TRY{
|
||||||
|
ValuePolicy::copy_value(
|
||||||
|
static_cast<const rep_type&>(entry(h)));
|
||||||
|
}
|
||||||
|
BOOST_CATCH(...){
|
||||||
|
factory().erase(h);
|
||||||
|
BOOST_RETHROW;
|
||||||
|
}
|
||||||
|
BOOST_CATCH_END
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool static_initializer;
|
||||||
|
static factory_type* static_factory_ptr;
|
||||||
|
static mutex_type* static_mutex_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename ValuePolicy,typename Tag,typename TrackingPolicy,
|
||||||
|
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
|
||||||
|
>
|
||||||
|
bool
|
||||||
|
flyweight_core<
|
||||||
|
ValuePolicy,Tag,TrackingPolicy,
|
||||||
|
FactorySpecifier,LockingPolicy,HolderSpecifier>::static_initializer=
|
||||||
|
flyweight_core<
|
||||||
|
ValuePolicy,Tag,TrackingPolicy,
|
||||||
|
FactorySpecifier,LockingPolicy,HolderSpecifier>::init();
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename ValuePolicy,typename Tag,typename TrackingPolicy,
|
||||||
|
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
|
||||||
|
>
|
||||||
|
typename flyweight_core<
|
||||||
|
ValuePolicy,Tag,TrackingPolicy,
|
||||||
|
FactorySpecifier,LockingPolicy,HolderSpecifier>::factory_type*
|
||||||
|
flyweight_core<
|
||||||
|
ValuePolicy,Tag,TrackingPolicy,
|
||||||
|
FactorySpecifier,LockingPolicy,HolderSpecifier>::static_factory_ptr=0;
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename ValuePolicy,typename Tag,typename TrackingPolicy,
|
||||||
|
typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
|
||||||
|
>
|
||||||
|
typename flyweight_core<
|
||||||
|
ValuePolicy,Tag,TrackingPolicy,
|
||||||
|
FactorySpecifier,LockingPolicy,HolderSpecifier>::mutex_type*
|
||||||
|
flyweight_core<
|
||||||
|
ValuePolicy,Tag,TrackingPolicy,
|
||||||
|
FactorySpecifier,LockingPolicy,HolderSpecifier>::static_mutex_ptr=0;
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
48
include/boost/flyweight/detail/handle_factory_adaptor.hpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_DETAIL_HANDLE_FACTORY_ADAPTOR_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_DETAIL_HANDLE_FACTORY_ADAPTOR_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Given a Factory and a Handle type constructible from and implicitly
|
||||||
|
* convertible to Factory::handle_type, handle_factory_adaptor
|
||||||
|
* adapts Factory to present Handle as the associated handle_type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
template<typename Factory,typename Handle,typename Entry>
|
||||||
|
struct handle_factory_adaptor:Factory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Handle handle_type;
|
||||||
|
|
||||||
|
handle_type insert(const Entry& x)
|
||||||
|
{
|
||||||
|
return static_cast<handle_type>(base().insert(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Factory& base(){return *this;}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
58
include/boost/flyweight/detail/not_placeholder_expr.hpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_DETAIL_NOT_PLACEHOLDER_EXPR_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_DETAIL_NOT_PLACEHOLDER_EXPR_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION can be inserted at the end
|
||||||
|
* of a class template parameter declaration:
|
||||||
|
* template<
|
||||||
|
* typename X0,...,typename Xn
|
||||||
|
* BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION
|
||||||
|
* >
|
||||||
|
* struct foo...
|
||||||
|
* to prevent instantiations from being treated as MPL placeholder
|
||||||
|
* expressions in the presence of placeholder arguments; this is useful
|
||||||
|
* to avoid masking of a metafunction class nested ::apply during
|
||||||
|
* MPL invocation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(__GNUC__, <4)||\
|
||||||
|
BOOST_WORKAROUND(__GNUC__,==4)&&(__GNUC_MINOR__<2)
|
||||||
|
/* The default trick on which the macro is based, namely adding a int=0
|
||||||
|
* defaulted template parameter, does not work in GCC prior to 4.2 due to
|
||||||
|
* an unfortunate compiler non-standard extension, as explained in
|
||||||
|
* http://lists.boost.org/boost-users/2007/07/29866.php
|
||||||
|
* We resort to an uglier technique, adding defaulted template parameters
|
||||||
|
* so as to exceed BOOST_MPL_LIMIT_METAFUNCTION_ARITY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/mpl/limits/arity.hpp>
|
||||||
|
#include <boost/preprocessor/facilities/intercept.hpp>
|
||||||
|
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION \
|
||||||
|
BOOST_PP_ENUM_TRAILING_PARAMS( \
|
||||||
|
BOOST_MPL_LIMIT_METAFUNCTION_ARITY,typename=int BOOST_PP_INTERCEPT)
|
||||||
|
#define BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION_DEF \
|
||||||
|
BOOST_PP_ENUM_TRAILING_PARAMS( \
|
||||||
|
BOOST_MPL_LIMIT_METAFUNCTION_ARITY,typename BOOST_PP_INTERCEPT)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION ,int=0
|
||||||
|
#define BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION_DEF ,int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
28
include/boost/flyweight/detail/perfect_fwd.hpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Brute force implementation of perfect forwarding overloads.
|
||||||
|
* Usage: include after having defined the argument macros:
|
||||||
|
* BOOST_FLYWEIGHT_PERFECT_FWD_NAME
|
||||||
|
* BOOST_FLYWEIGHT_PERFECT_FWD_BODY
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This user_definable macro limits the maximum number of arguments to
|
||||||
|
* be perfect forwarded. Beware combinatorial explosion: manual perfect
|
||||||
|
* forwarding for n arguments produces 2^n distinct overloads.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS)
|
||||||
|
#define BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS<=5
|
||||||
|
#include <boost/flyweight/detail/pp_perfect_fwd.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/flyweight/detail/dyn_perfect_fwd.hpp>
|
||||||
|
#endif
|
||||||
153
include/boost/flyweight/detail/pp_perfect_fwd.hpp
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* no include guards */
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=1
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWDS_1 \
|
||||||
|
template<typename T0> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(1)\
|
||||||
|
template<typename T0> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=2
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWDS_2 \
|
||||||
|
template<typename T0,typename T1> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(2)\
|
||||||
|
template<typename T0,typename T1> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(2)\
|
||||||
|
template<typename T0,typename T1> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(2)\
|
||||||
|
template<typename T0,typename T1> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=3
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWDS_3 \
|
||||||
|
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
|
||||||
|
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
|
||||||
|
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
|
||||||
|
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
|
||||||
|
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
|
||||||
|
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
|
||||||
|
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)\
|
||||||
|
template<typename T0,typename T1,typename T2> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(3)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=4
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWDS_4 \
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,const T3& t3)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(4)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=5
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWDS_5 \
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,T1& t1,const T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(T0& t0,const T1& t1,const T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,T1& t1,const T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,const T3& t3,T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)\
|
||||||
|
template<typename T0,typename T1,typename T2,typename T3,typename T4> BOOST_FLYWEIGHT_PERFECT_FWD_NAME(const T0& t0,const T1& t1,const T2& t2,const T3& t3,const T4& t4)BOOST_FLYWEIGHT_PERFECT_FWD_BODY(5)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==0
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS
|
||||||
|
#elif BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==1
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_1
|
||||||
|
#elif BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==2
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_1 \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_2
|
||||||
|
#elif BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==3
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_1 \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_2 \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_3
|
||||||
|
#elif BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==4
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_1 \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_2 \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_3 \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_4
|
||||||
|
#else /* BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS==5 */
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_1 \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_2 \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_3 \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_4 \
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWDS_5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* generate the overloads */
|
||||||
|
|
||||||
|
BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS
|
||||||
|
|
||||||
|
/* clean up */
|
||||||
|
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWD_OVERLOADS
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=1
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWDS_1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=2
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWDS_2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=3
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWDS_3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=4
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWDS_4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS>=5
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWDS_5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* user supplied argument macros */
|
||||||
|
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWD_NAME
|
||||||
|
#undef BOOST_FLYWEIGHT_PERFECT_FWD_BODY
|
||||||
81
include/boost/flyweight/detail/process_id.hpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_DETAIL_PROCESS_ID_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_DETAIL_PROCESS_ID_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
#if defined(BOOST_WINDOWS)&&!defined(BOOST_DISABLE_WIN32)
|
||||||
|
|
||||||
|
#if defined(BOOST_USE_WINDOWS_H)
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
namespace boost{
|
||||||
|
namespace flyweights{
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
extern "C" __declspec(dllimport)
|
||||||
|
unsigned long __stdcall GetCurrentProcessId(void);
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
} /* namespace flyweights */
|
||||||
|
} /* namespace boost */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
typedef unsigned long process_id_t;
|
||||||
|
|
||||||
|
inline process_id_t process_id()
|
||||||
|
{
|
||||||
|
return GetCurrentProcessId();
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#elif defined(BOOST_HAS_UNISTD_H)
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
typedef pid_t process_id_t;
|
||||||
|
|
||||||
|
inline process_id_t process_id()
|
||||||
|
{
|
||||||
|
return ::getpid();
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error Unknown platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
91
include/boost/flyweight/detail/recursive_lw_mutex.hpp
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_DETAIL_RECURSIVE_LW_MUTEX_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_DETAIL_RECURSIVE_LW_MUTEX_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Recursive lightweight mutex. Relies entirely on
|
||||||
|
* boost::detail::lightweight_mutex, except in Pthreads, where we
|
||||||
|
* explicitly use the PTHREAD_MUTEX_RECURSIVE attribute
|
||||||
|
* (lightweight_mutex uses the default mutex type instead).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
#if !defined(BOOST_HAS_PTHREADS)
|
||||||
|
#include <boost/detail/lightweight_mutex.hpp>
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
typedef boost::detail::lightweight_mutex recursive_lightweight_mutex;
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
#else
|
||||||
|
/* code shamelessly ripped from <boost/detail/lwm_pthreads.hpp> */
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
struct recursive_lightweight_mutex:noncopyable
|
||||||
|
{
|
||||||
|
recursive_lightweight_mutex()
|
||||||
|
{
|
||||||
|
pthread_mutexattr_t attr;
|
||||||
|
pthread_mutexattr_init(&attr);
|
||||||
|
pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
pthread_mutex_init(&m_,&attr);
|
||||||
|
pthread_mutexattr_destroy(&attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
~recursive_lightweight_mutex(){pthread_mutex_destroy(&m_);}
|
||||||
|
|
||||||
|
struct scoped_lock;
|
||||||
|
friend struct scoped_lock;
|
||||||
|
struct scoped_lock:noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
scoped_lock(recursive_lightweight_mutex& m):m_(m.m_)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&m_);
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock(){pthread_mutex_unlock(&m_);}
|
||||||
|
|
||||||
|
private:
|
||||||
|
pthread_mutex_t& m_;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
pthread_mutex_t m_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
50
include/boost/flyweight/detail/value_tag.hpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_DETAIL_VALUE_TAG_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_DETAIL_VALUE_TAG_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/parameter/parameters.hpp>
|
||||||
|
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
/* Three ways to indicate that a given class T is a value policy:
|
||||||
|
* 1. Make it derived from value_marker.
|
||||||
|
* 2. Specialize is_value to evaluate to boost::mpl::true_.
|
||||||
|
* 3. Pass it as value<T> when defining a flyweight type.
|
||||||
|
*
|
||||||
|
* For the time being the interface of value policies is not public.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct value_marker{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_value:is_base_and_derived<value_marker,T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename T=parameter::void_>
|
||||||
|
struct value:parameter::template_keyword<value<>,T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
44
include/boost/flyweight/factory_tag.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_FACTORY_TAG_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_FACTORY_TAG_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/parameter/parameters.hpp>
|
||||||
|
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
/* Three ways to indicate that a given class T is a factory specifier:
|
||||||
|
* 1. Make it derived from factory_marker.
|
||||||
|
* 2. Specialize is_factory to evaluate to boost::mpl::true_.
|
||||||
|
* 3. Pass it as factory<T> when defining a flyweight type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct factory_marker{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_factory:is_base_and_derived<factory_marker,T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename T=parameter::void_>
|
||||||
|
struct factory:parameter::template_keyword<factory<>,T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
407
include/boost/flyweight/flyweight.hpp
Normal file
@@ -0,0 +1,407 @@
|
|||||||
|
/* Flyweight class.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_FLYWEIGHT_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_FLYWEIGHT_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
#include <boost/flyweight/detail/default_value_policy.hpp>
|
||||||
|
#include <boost/flyweight/detail/flyweight_core.hpp>
|
||||||
|
#include <boost/flyweight/factory_tag.hpp>
|
||||||
|
#include <boost/flyweight/flyweight_fwd.hpp>
|
||||||
|
#include <boost/flyweight/locking_tag.hpp>
|
||||||
|
#include <boost/flyweight/simple_locking_fwd.hpp>
|
||||||
|
#include <boost/flyweight/static_holder_fwd.hpp>
|
||||||
|
#include <boost/flyweight/hashed_factory_fwd.hpp>
|
||||||
|
#include <boost/flyweight/holder_tag.hpp>
|
||||||
|
#include <boost/flyweight/refcounted_fwd.hpp>
|
||||||
|
#include <boost/flyweight/tag.hpp>
|
||||||
|
#include <boost/flyweight/tracking_tag.hpp>
|
||||||
|
#include <boost/mpl/assert.hpp>
|
||||||
|
#include <boost/mpl/if.hpp>
|
||||||
|
#include <boost/mpl/not.hpp>
|
||||||
|
#include <boost/mpl/or.hpp>
|
||||||
|
#include <boost/parameter/binding.hpp>
|
||||||
|
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||||
|
#include <boost/type_traits/is_same.hpp>
|
||||||
|
#include <boost/utility/swap.hpp>
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4521) /* multiple copy ctors */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
/* Used for the detection of unmatched template args in a
|
||||||
|
* flyweight instantiation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct unmatched_arg;
|
||||||
|
|
||||||
|
/* Boost.Parameter structures for use in flyweight.
|
||||||
|
* NB: these types are derived from instead of typedef'd to force their
|
||||||
|
* instantiation, which solves http://bugs.sun.com/view_bug.do?bug_id=6782987
|
||||||
|
* as found out by Simon Atanasyan.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct flyweight_signature:
|
||||||
|
parameter::parameters<
|
||||||
|
parameter::optional<
|
||||||
|
parameter::deduced<tag<> >,
|
||||||
|
detail::is_tag<boost::mpl::_>
|
||||||
|
>,
|
||||||
|
parameter::optional<
|
||||||
|
parameter::deduced<tracking<> >,
|
||||||
|
is_tracking<boost::mpl::_>
|
||||||
|
>,
|
||||||
|
parameter::optional<
|
||||||
|
parameter::deduced<factory<> >,
|
||||||
|
is_factory<boost::mpl::_>
|
||||||
|
>,
|
||||||
|
parameter::optional<
|
||||||
|
parameter::deduced<locking<> >,
|
||||||
|
is_locking<boost::mpl::_>
|
||||||
|
>,
|
||||||
|
parameter::optional<
|
||||||
|
parameter::deduced<holder<> >,
|
||||||
|
is_holder<boost::mpl::_>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
struct flyweight_unmatched_signature:
|
||||||
|
parameter::parameters<
|
||||||
|
parameter::optional<
|
||||||
|
parameter::deduced<
|
||||||
|
detail::unmatched_arg
|
||||||
|
>,
|
||||||
|
mpl::not_<
|
||||||
|
mpl::or_<
|
||||||
|
detail::is_tag<boost::mpl::_>,
|
||||||
|
is_tracking<boost::mpl::_>,
|
||||||
|
is_factory<boost::mpl::_>,
|
||||||
|
is_locking<boost::mpl::_>,
|
||||||
|
is_holder<boost::mpl::_>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T,
|
||||||
|
typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5
|
||||||
|
>
|
||||||
|
class flyweight
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename mpl::if_<
|
||||||
|
detail::is_value<T>,
|
||||||
|
T,
|
||||||
|
detail::default_value_policy<T>
|
||||||
|
>::type value_policy;
|
||||||
|
typedef typename detail::
|
||||||
|
flyweight_signature::bind<
|
||||||
|
Arg1,Arg2,Arg3,Arg4,Arg5
|
||||||
|
>::type args;
|
||||||
|
typedef typename parameter::binding<
|
||||||
|
args,tag<>,mpl::na
|
||||||
|
>::type tag_type;
|
||||||
|
typedef typename parameter::binding<
|
||||||
|
args,tracking<>,refcounted
|
||||||
|
>::type tracking_policy;
|
||||||
|
typedef typename parameter::binding<
|
||||||
|
args,factory<>,hashed_factory<>
|
||||||
|
>::type factory_specifier;
|
||||||
|
typedef typename parameter::binding<
|
||||||
|
args,locking<>,simple_locking
|
||||||
|
>::type locking_policy;
|
||||||
|
typedef typename parameter::binding<
|
||||||
|
args,holder<>,static_holder
|
||||||
|
>::type holder_specifier;
|
||||||
|
|
||||||
|
typedef typename detail::
|
||||||
|
flyweight_unmatched_signature::bind<
|
||||||
|
Arg1,Arg2,Arg3,Arg4,Arg5
|
||||||
|
>::type unmatched_args;
|
||||||
|
typedef typename parameter::binding<
|
||||||
|
unmatched_args,detail::unmatched_arg,
|
||||||
|
detail::unmatched_arg
|
||||||
|
>::type unmatched_arg_detected;
|
||||||
|
|
||||||
|
/* You have passed a type in the specification of a flyweight type that
|
||||||
|
* could not be interpreted as a valid argument.
|
||||||
|
*/
|
||||||
|
BOOST_MPL_ASSERT_MSG(
|
||||||
|
(is_same<unmatched_arg_detected,detail::unmatched_arg>::value),
|
||||||
|
INVALID_ARGUMENT_TO_FLYWEIGHT,
|
||||||
|
(flyweight));
|
||||||
|
|
||||||
|
typedef detail::flyweight_core<
|
||||||
|
value_policy,tag_type,tracking_policy,
|
||||||
|
factory_specifier,locking_policy,
|
||||||
|
holder_specifier
|
||||||
|
> core;
|
||||||
|
typedef typename core::handle_type handle_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename value_policy::key_type key_type;
|
||||||
|
typedef typename value_policy::value_type value_type;
|
||||||
|
|
||||||
|
/* static data initialization */
|
||||||
|
|
||||||
|
static bool init(){return core::init();}
|
||||||
|
|
||||||
|
class initializer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
initializer():b(init()){}
|
||||||
|
private:
|
||||||
|
bool b;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* construct/copy/destroy */
|
||||||
|
|
||||||
|
flyweight():h(core::insert(key_type())){}
|
||||||
|
flyweight(const flyweight& x):h(x.h){}
|
||||||
|
flyweight(flyweight& x):h(x.h){}
|
||||||
|
|
||||||
|
/* template ctors */
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit flyweight
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
|
||||||
|
:h(core::insert(BOOST_PP_ENUM_PARAMS(n,t))){}
|
||||||
|
#include <boost/flyweight/detail/perfect_fwd.hpp>
|
||||||
|
|
||||||
|
flyweight& operator=(const flyweight x){h=x.h;return *this;}
|
||||||
|
flyweight& operator=(const value_type& x){return operator=(flyweight(x));}
|
||||||
|
|
||||||
|
/* convertibility to underlying type */
|
||||||
|
|
||||||
|
const key_type& get_key()const{return core::key(h);}
|
||||||
|
const value_type& get()const{return core::value(h);}
|
||||||
|
operator const value_type&()const{return get();}
|
||||||
|
|
||||||
|
/* exact type equality */
|
||||||
|
|
||||||
|
friend bool operator==(const flyweight& x,const flyweight& y)
|
||||||
|
{
|
||||||
|
return &x.get()==&y.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* modifiers */
|
||||||
|
|
||||||
|
void swap(flyweight& x){boost::swap(h,x.h);}
|
||||||
|
|
||||||
|
private:
|
||||||
|
handle_type h;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(n) \
|
||||||
|
typename Arg##n##1,typename Arg##n##2,typename Arg##n##3, \
|
||||||
|
typename Arg##n##4,typename Arg##n##5
|
||||||
|
#define BOOST_FLYWEIGHT_TEMPL_ARGS(n) \
|
||||||
|
Arg##n##1,Arg##n##2,Arg##n##3,Arg##n##4,Arg##n##5
|
||||||
|
|
||||||
|
/* Comparison. Unlike exact type comparison defined above, intertype
|
||||||
|
* comparison just forwards to the underlying objects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
|
||||||
|
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
|
||||||
|
>
|
||||||
|
bool operator==(
|
||||||
|
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
|
||||||
|
const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
|
||||||
|
{
|
||||||
|
return x.get()==y.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
|
||||||
|
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
|
||||||
|
>
|
||||||
|
bool operator<(
|
||||||
|
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
|
||||||
|
const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
|
||||||
|
{
|
||||||
|
return x.get()<y.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||||
|
template<
|
||||||
|
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
|
||||||
|
typename T2
|
||||||
|
>
|
||||||
|
bool operator==(
|
||||||
|
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y)
|
||||||
|
{
|
||||||
|
return x.get()==y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T1,
|
||||||
|
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
|
||||||
|
>
|
||||||
|
bool operator==(
|
||||||
|
const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
|
||||||
|
{
|
||||||
|
return x==y.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
|
||||||
|
typename T2
|
||||||
|
>
|
||||||
|
bool operator<(
|
||||||
|
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y)
|
||||||
|
{
|
||||||
|
return x.get()<y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T1,
|
||||||
|
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
|
||||||
|
>
|
||||||
|
bool operator<(
|
||||||
|
const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y)
|
||||||
|
{
|
||||||
|
return x<y.get();
|
||||||
|
}
|
||||||
|
#endif /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
|
||||||
|
|
||||||
|
/* rest of comparison operators */
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(t,a1,a2) \
|
||||||
|
template<t> \
|
||||||
|
inline bool operator!=(const a1& x,const a2& y) \
|
||||||
|
{ \
|
||||||
|
return !(x==y); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template<t> \
|
||||||
|
inline bool operator>(const a1& x,const a2& y) \
|
||||||
|
{ \
|
||||||
|
return y<x; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template<t> \
|
||||||
|
inline bool operator>=(const a1& x,const a2& y) \
|
||||||
|
{ \
|
||||||
|
return !(x<y); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template<t> \
|
||||||
|
inline bool operator<=(const a1& x,const a2& y) \
|
||||||
|
{ \
|
||||||
|
return !(y<x); \
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
|
||||||
|
typename T1 BOOST_PP_COMMA()
|
||||||
|
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
|
||||||
|
typename T2 BOOST_PP_COMMA()
|
||||||
|
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
|
||||||
|
flyweight<
|
||||||
|
T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
|
||||||
|
>,
|
||||||
|
flyweight<
|
||||||
|
T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
|
||||||
|
>)
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||||
|
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
|
||||||
|
typename T1 BOOST_PP_COMMA()
|
||||||
|
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
|
||||||
|
typename T2,
|
||||||
|
flyweight<
|
||||||
|
T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
|
||||||
|
>,
|
||||||
|
T2)
|
||||||
|
|
||||||
|
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS(
|
||||||
|
typename T1 BOOST_PP_COMMA()
|
||||||
|
typename T2 BOOST_PP_COMMA()
|
||||||
|
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
|
||||||
|
T1,
|
||||||
|
flyweight<
|
||||||
|
T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
|
||||||
|
>)
|
||||||
|
#endif /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
|
||||||
|
|
||||||
|
/* specialized algorithms */
|
||||||
|
|
||||||
|
template<typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)>
|
||||||
|
void swap(
|
||||||
|
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x,
|
||||||
|
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& y)
|
||||||
|
{
|
||||||
|
x.swap(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
|
||||||
|
BOOST_TEMPLATED_STREAM_COMMA
|
||||||
|
typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
|
||||||
|
>
|
||||||
|
BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& operator<<(
|
||||||
|
BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& out,
|
||||||
|
const flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x)
|
||||||
|
{
|
||||||
|
return out<<x.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
|
||||||
|
BOOST_TEMPLATED_STREAM_COMMA
|
||||||
|
typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
|
||||||
|
>
|
||||||
|
BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& operator>>(
|
||||||
|
BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& in,
|
||||||
|
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x)
|
||||||
|
{
|
||||||
|
typedef typename flyweight<
|
||||||
|
T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)
|
||||||
|
>::value_type value_type;
|
||||||
|
|
||||||
|
/* value_type need not be default ctble but must be copy ctble */
|
||||||
|
value_type t(x.get());
|
||||||
|
in>>t;
|
||||||
|
x=t;
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#undef BOOST_FLYWEIGHT_COMPLETE_COMP_OPS
|
||||||
|
#undef BOOST_FLYWEIGHT_TEMPL_ARGS
|
||||||
|
#undef BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
166
include/boost/flyweight/flyweight_fwd.hpp
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_FLYWEIGHT_FWD_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_FLYWEIGHT_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/detail/templated_streams.hpp>
|
||||||
|
#include <boost/parameter/parameters.hpp>
|
||||||
|
#include <boost/preprocessor/punctuation/comma.hpp>
|
||||||
|
#include <iosfwd>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T,
|
||||||
|
typename Arg1=parameter::void_,
|
||||||
|
typename Arg2=parameter::void_,
|
||||||
|
typename Arg3=parameter::void_,
|
||||||
|
typename Arg4=parameter::void_,
|
||||||
|
typename Arg5=parameter::void_
|
||||||
|
>
|
||||||
|
class flyweight;
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(n) \
|
||||||
|
typename Arg##n##1,typename Arg##n##2,typename Arg##n##3, \
|
||||||
|
typename Arg##n##4,typename Arg##n##5
|
||||||
|
#define BOOST_FLYWEIGHT_TEMPL_ARGS(n) \
|
||||||
|
Arg##n##1,Arg##n##2,Arg##n##3,Arg##n##4,Arg##n##5
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
|
||||||
|
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
|
||||||
|
>
|
||||||
|
bool operator==(
|
||||||
|
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
|
||||||
|
const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y);
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
|
||||||
|
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
|
||||||
|
>
|
||||||
|
bool operator<(
|
||||||
|
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,
|
||||||
|
const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y);
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||||
|
template<
|
||||||
|
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
|
||||||
|
typename T2
|
||||||
|
>
|
||||||
|
bool operator==(
|
||||||
|
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y);
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T1,
|
||||||
|
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
|
||||||
|
>
|
||||||
|
bool operator==(
|
||||||
|
const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y);
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T1,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1),
|
||||||
|
typename T2
|
||||||
|
>
|
||||||
|
bool operator<(
|
||||||
|
const flyweight<T1,BOOST_FLYWEIGHT_TEMPL_ARGS(1)>& x,const T2& y);
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename T1,
|
||||||
|
typename T2,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2)
|
||||||
|
>
|
||||||
|
bool operator<(
|
||||||
|
const T1& x,const flyweight<T2,BOOST_FLYWEIGHT_TEMPL_ARGS(2)>& y);
|
||||||
|
#endif /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_COMPLETE_COMP_OPS_DECL(t,a1,a2) \
|
||||||
|
template<t> \
|
||||||
|
inline bool operator!=(const a1& x,const a2& y); \
|
||||||
|
\
|
||||||
|
template<t> \
|
||||||
|
inline bool operator>(const a1& x,const a2& y); \
|
||||||
|
\
|
||||||
|
template<t> \
|
||||||
|
inline bool operator>=(const a1& x,const a2& y); \
|
||||||
|
\
|
||||||
|
template<t> \
|
||||||
|
inline bool operator<=(const a1& x,const a2& y); \
|
||||||
|
|
||||||
|
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS_DECL(
|
||||||
|
typename T1 BOOST_PP_COMMA()
|
||||||
|
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
|
||||||
|
typename T2 BOOST_PP_COMMA()
|
||||||
|
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
|
||||||
|
flyweight<
|
||||||
|
T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
|
||||||
|
>,
|
||||||
|
flyweight<
|
||||||
|
T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
|
||||||
|
>)
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||||
|
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS_DECL(
|
||||||
|
typename T1 BOOST_PP_COMMA()
|
||||||
|
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(1) BOOST_PP_COMMA()
|
||||||
|
typename T2,
|
||||||
|
flyweight<
|
||||||
|
T1 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(1)
|
||||||
|
>,
|
||||||
|
T2)
|
||||||
|
|
||||||
|
BOOST_FLYWEIGHT_COMPLETE_COMP_OPS_DECL(
|
||||||
|
typename T1 BOOST_PP_COMMA()
|
||||||
|
typename T2 BOOST_PP_COMMA()
|
||||||
|
BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(2),
|
||||||
|
T1,
|
||||||
|
flyweight<
|
||||||
|
T2 BOOST_PP_COMMA() BOOST_FLYWEIGHT_TEMPL_ARGS(2)
|
||||||
|
>)
|
||||||
|
#endif /* !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) */
|
||||||
|
|
||||||
|
template<typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)>
|
||||||
|
inline void swap(
|
||||||
|
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x,
|
||||||
|
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& y);
|
||||||
|
|
||||||
|
template<
|
||||||
|
BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
|
||||||
|
BOOST_TEMPLATED_STREAM_COMMA
|
||||||
|
typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
|
||||||
|
>
|
||||||
|
inline BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& operator<<(
|
||||||
|
BOOST_TEMPLATED_STREAM(ostream,ElemType,Traits)& out,
|
||||||
|
const flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x);
|
||||||
|
|
||||||
|
template<
|
||||||
|
BOOST_TEMPLATED_STREAM_ARGS(ElemType,Traits)
|
||||||
|
BOOST_TEMPLATED_STREAM_COMMA
|
||||||
|
typename T,BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS(_)
|
||||||
|
>
|
||||||
|
inline BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& operator>>(
|
||||||
|
BOOST_TEMPLATED_STREAM(istream,ElemType,Traits)& in,
|
||||||
|
flyweight<T,BOOST_FLYWEIGHT_TEMPL_ARGS(_)>& x);
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
using flyweights::flyweight;
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#undef BOOST_FLYWEIGHT_COMPLETE_COMP_OPS_DECL
|
||||||
|
#undef BOOST_FLYWEIGHT_TEMPL_ARGS
|
||||||
|
#undef BOOST_FLYWEIGHT_TYPENAME_TEMPL_ARGS
|
||||||
|
|
||||||
|
#endif
|
||||||
128
include/boost/flyweight/hashed_factory.hpp
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_HASHED_FACTORY_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_HASHED_FACTORY_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/factory_tag.hpp>
|
||||||
|
#include <boost/flyweight/hashed_factory_fwd.hpp>
|
||||||
|
#include <boost/multi_index_container.hpp>
|
||||||
|
#include <boost/multi_index/identity.hpp>
|
||||||
|
#include <boost/multi_index/hashed_index.hpp>
|
||||||
|
#include <boost/mpl/aux_/lambda_support.hpp>
|
||||||
|
#include <boost/mpl/if.hpp>
|
||||||
|
|
||||||
|
/* Flyweight factory based on a hashed container implemented
|
||||||
|
* with Boost.MultiIndex.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Entry,typename Key,
|
||||||
|
typename Hash,typename Pred,typename Allocator
|
||||||
|
>
|
||||||
|
class hashed_factory_class:public factory_marker
|
||||||
|
{
|
||||||
|
struct index_list:
|
||||||
|
boost::mpl::vector1<
|
||||||
|
multi_index::hashed_unique<
|
||||||
|
multi_index::identity<Entry>,
|
||||||
|
typename boost::mpl::if_<
|
||||||
|
mpl::is_na<Hash>,
|
||||||
|
hash<Key>,
|
||||||
|
Hash
|
||||||
|
>::type,
|
||||||
|
typename boost::mpl::if_<
|
||||||
|
mpl::is_na<Pred>,
|
||||||
|
std::equal_to<Key>,
|
||||||
|
Pred
|
||||||
|
>::type
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
typedef multi_index::multi_index_container<
|
||||||
|
Entry,
|
||||||
|
index_list,
|
||||||
|
typename boost::mpl::if_<
|
||||||
|
mpl::is_na<Allocator>,
|
||||||
|
std::allocator<Entry>,
|
||||||
|
Allocator
|
||||||
|
>::type
|
||||||
|
> container_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef const Entry* handle_type;
|
||||||
|
|
||||||
|
handle_type insert(const Entry& x)
|
||||||
|
{
|
||||||
|
return &*cont.insert(x).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase(handle_type h)
|
||||||
|
{
|
||||||
|
cont.erase(cont.iterator_to(*h));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Entry& entry(handle_type h){return *h;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
container_type cont;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef hashed_factory_class type;
|
||||||
|
BOOST_MPL_AUX_LAMBDA_SUPPORT(
|
||||||
|
5,hashed_factory_class,(Entry,Key,Hash,Pred,Allocator))
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||||
|
/* This is preferred to deriving from factory_marker since checking for
|
||||||
|
* derivation forces the instantiation of the specifier, which is not
|
||||||
|
* needed when the specifier is a placeholder expression.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Entry,typename Key,
|
||||||
|
typename Hash,typename Pred,typename Allocator
|
||||||
|
>
|
||||||
|
struct is_factory<hashed_factory_class<Entry,Key,Hash,Pred,Allocator> >:
|
||||||
|
boost::mpl::true_{};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* hashed_factory_class specifier */
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Hash,typename Pred,typename Allocator
|
||||||
|
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION_DEF
|
||||||
|
>
|
||||||
|
struct hashed_factory:factory_marker
|
||||||
|
{
|
||||||
|
template<typename Entry,typename Key>
|
||||||
|
struct apply:
|
||||||
|
mpl::apply2<
|
||||||
|
hashed_factory_class<
|
||||||
|
boost::mpl::_1,boost::mpl::_2,Hash,Pred,Allocator
|
||||||
|
>,
|
||||||
|
Entry,Key
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
40
include/boost/flyweight/hashed_factory_fwd.hpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_HASHED_FACTORY_FWD_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_HASHED_FACTORY_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/detail/not_placeholder_expr.hpp>
|
||||||
|
#include <boost/mpl/aux_/na.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Entry,typename Key,
|
||||||
|
typename Hash=mpl::na,typename Pred=mpl::na,typename Allocator=mpl::na
|
||||||
|
>
|
||||||
|
class hashed_factory_class;
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Hash=mpl::na,typename Pred=mpl::na,typename Allocator=mpl::na
|
||||||
|
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION
|
||||||
|
>
|
||||||
|
struct hashed_factory;
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
44
include/boost/flyweight/holder_tag.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_HOLDER_TAG_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_HOLDER_TAG_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/parameter/parameters.hpp>
|
||||||
|
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
/* Three ways to indicate that a given class T is a holder specifier:
|
||||||
|
* 1. Make it derived from holder_marker.
|
||||||
|
* 2. Specialize is_holder to evaluate to boost::mpl::true_.
|
||||||
|
* 3. Pass it as holder<T> when defining a flyweight type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct holder_marker{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_holder:is_base_and_derived<holder_marker,T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename T=parameter::void_>
|
||||||
|
struct holder:parameter::template_keyword<holder<>,T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
202
include/boost/flyweight/intermodule_holder.hpp
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_INTERMODULE_HOLDER_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_INTERMODULE_HOLDER_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/holder_tag.hpp>
|
||||||
|
#include <boost/flyweight/intermodule_holder_fwd.hpp>
|
||||||
|
#include <boost/flyweight/detail/process_id.hpp>
|
||||||
|
#include <boost/functional/hash.hpp>
|
||||||
|
#include <boost/interprocess/sync/named_mutex.hpp>
|
||||||
|
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||||
|
#include <boost/interprocess/managed_shared_memory.hpp>
|
||||||
|
#include <boost/mpl/aux_/lambda_support.hpp>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
/* intermodule_holder_class guarantees a unique instance across all dynamic
|
||||||
|
* modules of a program.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
struct intermodule_holder_class:holder_marker
|
||||||
|
{
|
||||||
|
static C& get()
|
||||||
|
{
|
||||||
|
static instantiator instance;
|
||||||
|
return instance.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct instantiator
|
||||||
|
{
|
||||||
|
instantiator():
|
||||||
|
mutex(interprocess::open_or_create,compute_mutex_name()),
|
||||||
|
seg(interprocess::open_or_create,compute_segment_name(),16384),
|
||||||
|
ppref(0),
|
||||||
|
pc(0)
|
||||||
|
{
|
||||||
|
/* Instance creation is done according to a two-phase protocol so
|
||||||
|
* that we call "new" in an unlocked situation, thus minimizing the
|
||||||
|
* chance of leaving dangling locks due to catastrophic failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
interprocess::scoped_lock<interprocess::named_mutex> lock(mutex);
|
||||||
|
ppref=seg.find_or_construct<referenced_instance*>(
|
||||||
|
typeid(C).name())((referenced_instance*)0);
|
||||||
|
if(*ppref){
|
||||||
|
/* As in some OSes Boost.Interprocess memory segments can outlive
|
||||||
|
* their associated processes, there is a possibility that we
|
||||||
|
* retrieve a dangling pointer (coming from a previous aborted run,
|
||||||
|
* for instance). Try to protect against this by checking that
|
||||||
|
* the contents of the pointed object are consistent.
|
||||||
|
*/
|
||||||
|
if(std::strcmp(segment_name,(*ppref)->segment_name)!=0){
|
||||||
|
*ppref=0; /* dangling pointer! */
|
||||||
|
}
|
||||||
|
else ++((*ppref)->ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!*ppref){
|
||||||
|
std::auto_ptr<referenced_instance> apc(
|
||||||
|
new referenced_instance(segment_name));
|
||||||
|
interprocess::scoped_lock<interprocess::named_mutex> lock(mutex);
|
||||||
|
ppref=seg.find_or_construct<referenced_instance*>(
|
||||||
|
typeid(C).name())((referenced_instance*)0);
|
||||||
|
if(!*ppref)*ppref=apc.release();
|
||||||
|
++((*ppref)->ref);
|
||||||
|
}
|
||||||
|
pc=&(*ppref)->c;
|
||||||
|
}
|
||||||
|
|
||||||
|
~instantiator()
|
||||||
|
{
|
||||||
|
/* As in construction time, actual deletion is performed outside the
|
||||||
|
* lock to avoid leaving the lock dangling in case of crash.
|
||||||
|
*/
|
||||||
|
|
||||||
|
referenced_instance* pref=0;
|
||||||
|
{
|
||||||
|
interprocess::scoped_lock<interprocess::named_mutex> lock(mutex);
|
||||||
|
if(--((*ppref)->ref)==0){
|
||||||
|
pref=*ppref;
|
||||||
|
*ppref=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pref)delete pref;
|
||||||
|
}
|
||||||
|
|
||||||
|
C& get()const{return *pc;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Although mutex and seg are system-wide, their names intend to
|
||||||
|
* make them specific for the current process and type, hence their
|
||||||
|
* containing process id and type id info.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char mutex_name[128];
|
||||||
|
char segment_name[128];
|
||||||
|
|
||||||
|
const char* compute_mutex_name()
|
||||||
|
{
|
||||||
|
std::sprintf(
|
||||||
|
mutex_name,
|
||||||
|
"boost_flyweight_intermodule_holder_mutex_"
|
||||||
|
"%ld_%u_%u_%u_%u",
|
||||||
|
(long)detail::process_id(),
|
||||||
|
(unsigned)compute_hash(typeid(C).name(),0),
|
||||||
|
(unsigned)compute_hash(typeid(C).name(),1),
|
||||||
|
(unsigned)compute_hash(typeid(C).name(),2),
|
||||||
|
(unsigned)compute_hash(typeid(C).name(),3));
|
||||||
|
|
||||||
|
return mutex_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* compute_segment_name()
|
||||||
|
{
|
||||||
|
std::sprintf(
|
||||||
|
segment_name,
|
||||||
|
"boost_flyweight_intermodule_holder_segment_"
|
||||||
|
"%ld_%u_%u_%u_%u",
|
||||||
|
(long)detail::process_id(),
|
||||||
|
(unsigned)compute_hash(typeid(C).name(),0),
|
||||||
|
(unsigned)compute_hash(typeid(C).name(),1),
|
||||||
|
(unsigned)compute_hash(typeid(C).name(),2),
|
||||||
|
(unsigned)compute_hash(typeid(C).name(),3));
|
||||||
|
|
||||||
|
return segment_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::size_t compute_hash(const char* str,std::size_t off)
|
||||||
|
{
|
||||||
|
std::size_t len=std::strlen(str);
|
||||||
|
if(off>len)off=len;
|
||||||
|
return hash_range(str+off,str+len);
|
||||||
|
}
|
||||||
|
|
||||||
|
interprocess::named_mutex mutex;
|
||||||
|
interprocess::managed_shared_memory seg;
|
||||||
|
struct referenced_instance
|
||||||
|
{
|
||||||
|
referenced_instance(const char* segment_name_):ref(0)
|
||||||
|
{
|
||||||
|
strcpy(segment_name,segment_name_);
|
||||||
|
}
|
||||||
|
|
||||||
|
~referenced_instance(){segment_name[0]='\0';}
|
||||||
|
|
||||||
|
char segment_name[128]; /* used to detect dangling pointers */
|
||||||
|
mutable long ref;
|
||||||
|
C c;
|
||||||
|
}** ppref;
|
||||||
|
C* pc;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef intermodule_holder_class type;
|
||||||
|
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,intermodule_holder_class,(C))
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||||
|
/* This is preferred to deriving from holder_marker since checking for
|
||||||
|
* derivation forces the instantiation of the specifier, which is not
|
||||||
|
* needed when the specifier is a placeholder expression.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
struct is_holder<intermodule_holder_class<C> >:boost::mpl::true_{};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* intermodule_holder_class specifier */
|
||||||
|
|
||||||
|
struct intermodule_holder:holder_marker
|
||||||
|
{
|
||||||
|
template<typename C>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef intermodule_holder_class<C> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
29
include/boost/flyweight/intermodule_holder_fwd.hpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_INTERMODULE_HOLDER_FWD_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_INTERMODULE_HOLDER_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
struct intermodule_holder_class;
|
||||||
|
|
||||||
|
struct intermodule_holder;
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
238
include/boost/flyweight/key_value.hpp
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_KEY_VALUE_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_KEY_VALUE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/flyweight/detail/value_tag.hpp>
|
||||||
|
#include <boost/flyweight/key_value_fwd.hpp>
|
||||||
|
#include <boost/mpl/assert.hpp>
|
||||||
|
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||||
|
#include <boost/type_traits/aligned_storage.hpp>
|
||||||
|
#include <boost/type_traits/alignment_of.hpp>
|
||||||
|
#include <boost/type_traits/is_same.hpp>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
/* key-value policy: flywewight lookup is based on Key, which also serves
|
||||||
|
* to construct Value only when needed (new factory entry). key_value is
|
||||||
|
* used to avoid the construction of temporary values when such construction
|
||||||
|
* is expensive.
|
||||||
|
* Optionally, KeyFromValue extracts the key from a value, which
|
||||||
|
* is needed in expressions like this:
|
||||||
|
*
|
||||||
|
* typedef flyweight<key_value<Key,Value> > fw_t;
|
||||||
|
* fw_t fw;
|
||||||
|
* Value v;
|
||||||
|
* fw=v; // no key explicitly given
|
||||||
|
*
|
||||||
|
* If no KeyFromValue is provided, this latter expression fails to compile.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
template<typename Key,typename Value,typename KeyFromValue>
|
||||||
|
struct optimized_key_value:value_marker
|
||||||
|
{
|
||||||
|
typedef Key key_type;
|
||||||
|
typedef Value value_type;
|
||||||
|
|
||||||
|
class rep_type
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* template ctors */
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit rep_type
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
|
||||||
|
:value_ptr(0) \
|
||||||
|
{ \
|
||||||
|
new(spc_ptr())key_type(BOOST_PP_ENUM_PARAMS(n,t)); \
|
||||||
|
}
|
||||||
|
#include <boost/flyweight/detail/perfect_fwd.hpp>
|
||||||
|
|
||||||
|
rep_type(const value_type& x):value_ptr(&x){}
|
||||||
|
|
||||||
|
rep_type(const rep_type& x):value_ptr(x.value_ptr)
|
||||||
|
{
|
||||||
|
if(!x.value_ptr)new(key_ptr())key_type(*x.key_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
~rep_type()
|
||||||
|
{
|
||||||
|
if(!value_ptr) key_ptr()->~key_type();
|
||||||
|
else if(value_cted())value_ptr->~value_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
operator const key_type&()const
|
||||||
|
{
|
||||||
|
if(value_ptr)return key_from_value(*value_ptr);
|
||||||
|
else return *key_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
operator const value_type&()const
|
||||||
|
{
|
||||||
|
/* This is always called after construct_value() or copy_value(),
|
||||||
|
* so we access spc directly rather than through value_ptr to
|
||||||
|
* save us an indirection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return *static_cast<value_type*>(spc_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend struct optimized_key_value;
|
||||||
|
|
||||||
|
void* spc_ptr()const{return static_cast<void*>(&spc);}
|
||||||
|
bool value_cted()const{return value_ptr==spc_ptr();}
|
||||||
|
|
||||||
|
key_type* key_ptr()const
|
||||||
|
{
|
||||||
|
return static_cast<key_type*>(static_cast<void*>(&spc));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const key_type& key_from_value(const value_type& x)
|
||||||
|
{
|
||||||
|
KeyFromValue k;
|
||||||
|
return k(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void construct_value()const
|
||||||
|
{
|
||||||
|
if(!value_cted()){
|
||||||
|
/* value_ptr must be ==0, oherwise copy_value would have been called */
|
||||||
|
|
||||||
|
key_type k(*key_ptr());
|
||||||
|
key_ptr()->~key_type();
|
||||||
|
value_ptr= /* guarantees key won't be re-dted at ~rep_type if the */
|
||||||
|
static_cast<value_type*>(spc_ptr())+1; /* next statement throws */
|
||||||
|
value_ptr=new(spc_ptr())value_type(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_value()const
|
||||||
|
{
|
||||||
|
if(!value_cted())value_ptr=new(spc_ptr())value_type(*value_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutable typename boost::aligned_storage<
|
||||||
|
(sizeof(key_type)>sizeof(value_type))?
|
||||||
|
sizeof(key_type):sizeof(value_type),
|
||||||
|
(boost::alignment_of<key_type>::value >
|
||||||
|
boost::alignment_of<value_type>::value)?
|
||||||
|
boost::alignment_of<key_type>::value:
|
||||||
|
boost::alignment_of<value_type>::value
|
||||||
|
>::type spc;
|
||||||
|
mutable const value_type* value_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void construct_value(const rep_type& r)
|
||||||
|
{
|
||||||
|
r.construct_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copy_value(const rep_type& r)
|
||||||
|
{
|
||||||
|
r.copy_value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Key,typename Value>
|
||||||
|
struct regular_key_value:value_marker
|
||||||
|
{
|
||||||
|
typedef Key key_type;
|
||||||
|
typedef Value value_type;
|
||||||
|
|
||||||
|
class rep_type
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* template ctors */
|
||||||
|
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit rep_type
|
||||||
|
#define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \
|
||||||
|
:key(BOOST_PP_ENUM_PARAMS(n,t)),value_ptr(0){}
|
||||||
|
#include <boost/flyweight/detail/perfect_fwd.hpp>
|
||||||
|
|
||||||
|
rep_type(const value_type& x):key(no_key_from_value_failure()){}
|
||||||
|
|
||||||
|
rep_type(const rep_type& x):key(x.key),value_ptr(0){}
|
||||||
|
|
||||||
|
~rep_type()
|
||||||
|
{
|
||||||
|
if(value_ptr)value_ptr->~value_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
operator const key_type&()const{return key;}
|
||||||
|
|
||||||
|
operator const value_type&()const
|
||||||
|
{
|
||||||
|
/* This is always called after construct_value(),so we access spc
|
||||||
|
* directly rather than through value_ptr to save us an indirection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return *static_cast<value_type*>(spc_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend struct regular_key_value;
|
||||||
|
|
||||||
|
void* spc_ptr()const{return static_cast<void*>(&spc);}
|
||||||
|
|
||||||
|
struct no_key_from_value_failure
|
||||||
|
{
|
||||||
|
BOOST_MPL_ASSERT_MSG(
|
||||||
|
false,
|
||||||
|
NO_KEY_FROM_VALUE_CONVERSION_PROVIDED,
|
||||||
|
(key_type,value_type));
|
||||||
|
|
||||||
|
operator const key_type&()const;
|
||||||
|
};
|
||||||
|
|
||||||
|
void construct_value()const
|
||||||
|
{
|
||||||
|
if(!value_ptr)value_ptr=new(spc_ptr())value_type(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
key_type key;
|
||||||
|
mutable typename boost::aligned_storage<
|
||||||
|
sizeof(value_type),
|
||||||
|
boost::alignment_of<value_type>::value
|
||||||
|
>::type spc;
|
||||||
|
mutable const value_type* value_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void construct_value(const rep_type& r)
|
||||||
|
{
|
||||||
|
r.construct_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copy_value(const rep_type&){}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
template<typename Key,typename Value,typename KeyFromValue>
|
||||||
|
struct key_value:
|
||||||
|
mpl::if_<
|
||||||
|
is_same<KeyFromValue,no_key_from_value>,
|
||||||
|
detail::regular_key_value<Key,Value>,
|
||||||
|
detail::optimized_key_value<Key,Value,KeyFromValue>
|
||||||
|
>::type
|
||||||
|
{};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
29
include/boost/flyweight/key_value_fwd.hpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_KEY_VALUE_FWD_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_KEY_VALUE_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
struct no_key_from_value;
|
||||||
|
|
||||||
|
template<typename Key,typename Value,typename KeyFromValue=no_key_from_value>
|
||||||
|
struct key_value;
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
44
include/boost/flyweight/locking_tag.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_LOCKING_TAG_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_LOCKING_TAG_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/parameter/parameters.hpp>
|
||||||
|
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
/* Three ways to indicate that a given class T is a locking policy:
|
||||||
|
* 1. Make it derived from locking_marker.
|
||||||
|
* 2. Specialize is_locking to evaluate to boost::mpl::true_.
|
||||||
|
* 3. Pass it as locking<T> when defining a flyweight type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct locking_marker{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_locking:is_base_and_derived<locking_marker,T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename T=parameter::void_>
|
||||||
|
struct locking:parameter::template_keyword<locking<>,T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
36
include/boost/flyweight/no_locking.hpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_NO_LOCKING_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_NO_LOCKING_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/no_locking_fwd.hpp>
|
||||||
|
#include <boost/flyweight/locking_tag.hpp>
|
||||||
|
|
||||||
|
/* null locking policy */
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
struct no_locking:locking_marker
|
||||||
|
{
|
||||||
|
struct mutex_type{};
|
||||||
|
typedef mutex_type lock_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
26
include/boost/flyweight/no_locking_fwd.hpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_NO_LOCKING_FWD_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_NO_LOCKING_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
struct no_locking;
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
46
include/boost/flyweight/no_tracking.hpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_NO_TRACKING_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_NO_TRACKING_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/no_tracking_fwd.hpp>
|
||||||
|
#include <boost/flyweight/tracking_tag.hpp>
|
||||||
|
|
||||||
|
/* Null tracking policy: elements are never erased from the factory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
struct no_tracking:tracking_marker
|
||||||
|
{
|
||||||
|
struct entry_type
|
||||||
|
{
|
||||||
|
template<typename Value,typename Key>
|
||||||
|
struct apply{typedef Value type;};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct handle_type
|
||||||
|
{
|
||||||
|
template<typename Handle,typename TrackingHelper>
|
||||||
|
struct apply{typedef Handle type;};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
26
include/boost/flyweight/no_tracking_fwd.hpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_NO_TRACKING_FWD_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_NO_TRACKING_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
struct no_tracking;
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
152
include/boost/flyweight/refcounted.hpp
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_REFCOUNTED_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_REFCOUNTED_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/detail/atomic_count.hpp>
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
#include <boost/flyweight/refcounted_fwd.hpp>
|
||||||
|
#include <boost/flyweight/tracking_tag.hpp>
|
||||||
|
#include <boost/utility/swap.hpp>
|
||||||
|
|
||||||
|
/* Refcounting tracking policy: values have an embedded ref count,
|
||||||
|
* when this goes down to zero the element is erased from the
|
||||||
|
* factory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
template<typename Value,typename Key>
|
||||||
|
class refcounted_value
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit refcounted_value(const Value& x_):
|
||||||
|
x(x_),ref(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
refcounted_value(const refcounted_value& r):
|
||||||
|
x(r.x),ref(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~refcounted_value()
|
||||||
|
{
|
||||||
|
/* count()!=0 most likely indicates that the flyweight factory
|
||||||
|
* has been destructed before some of the flyweight objects using
|
||||||
|
* it. Check for static initialization order problems with this
|
||||||
|
* flyweight type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOST_ASSERT(count()==0);
|
||||||
|
}
|
||||||
|
|
||||||
|
refcounted_value& operator=(const refcounted_value& r)
|
||||||
|
{
|
||||||
|
x=r.x;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator const Value&()const{return x;}
|
||||||
|
operator const Key&()const{return x;}
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||||
|
private:
|
||||||
|
template<typename,typename> friend class refcounted_handle;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
long count()const{return ref;}
|
||||||
|
void add_ref()const{++ref;}
|
||||||
|
bool release()const{return (--ref==0);}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Value x;
|
||||||
|
mutable boost::detail::atomic_count ref;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Handle,typename TrackingHelper>
|
||||||
|
class refcounted_handle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit refcounted_handle(const Handle& h_):h(h_)
|
||||||
|
{
|
||||||
|
TrackingHelper::entry(*this).add_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
refcounted_handle(const refcounted_handle& x):h(x.h)
|
||||||
|
{
|
||||||
|
TrackingHelper::entry(*this).add_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
refcounted_handle& operator=(refcounted_handle x)
|
||||||
|
{
|
||||||
|
swap(*this,x);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~refcounted_handle()
|
||||||
|
{
|
||||||
|
if(TrackingHelper::entry(*this).release()){
|
||||||
|
TrackingHelper::erase(*this,check_erase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator const Handle&()const{return h;}
|
||||||
|
|
||||||
|
friend void swap(refcounted_handle& x, refcounted_handle& y)
|
||||||
|
{
|
||||||
|
boost::swap(x.h,y.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool check_erase(const refcounted_handle& x)
|
||||||
|
{
|
||||||
|
return TrackingHelper::entry(x).count()==0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle h;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
struct refcounted:tracking_marker
|
||||||
|
{
|
||||||
|
struct entry_type
|
||||||
|
{
|
||||||
|
template<typename Value,typename Key>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef detail::refcounted_value<Value,Key> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct handle_type
|
||||||
|
{
|
||||||
|
template<typename Handle,typename TrackingHelper>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef detail::refcounted_handle<Handle,TrackingHelper> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
26
include/boost/flyweight/refcounted_fwd.hpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_REFCOUNTED_FWD_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_REFCOUNTED_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
struct refcounted;
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
96
include/boost/flyweight/set_factory.hpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_SET_FACTORY_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_SET_FACTORY_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/detail/allocator_utilities.hpp>
|
||||||
|
#include <boost/flyweight/assoc_container_factory.hpp>
|
||||||
|
#include <boost/flyweight/factory_tag.hpp>
|
||||||
|
#include <boost/flyweight/set_factory_fwd.hpp>
|
||||||
|
#include <boost/mpl/aux_/lambda_support.hpp>
|
||||||
|
#include <boost/mpl/if.hpp>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
/* Particularization of assoc_container_factory_class using a set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Entry,typename Key,
|
||||||
|
typename Compare,typename Allocator
|
||||||
|
>
|
||||||
|
class set_factory_class:
|
||||||
|
public assoc_container_factory_class<
|
||||||
|
std::set<
|
||||||
|
Entry,
|
||||||
|
typename boost::mpl::if_<
|
||||||
|
mpl::is_na<Compare>,
|
||||||
|
std::less<Key>,
|
||||||
|
Compare
|
||||||
|
>::type,
|
||||||
|
typename boost::mpl::if_<
|
||||||
|
mpl::is_na<Allocator>,
|
||||||
|
std::allocator<Entry>,
|
||||||
|
Allocator
|
||||||
|
>::type
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef set_factory_class type;
|
||||||
|
BOOST_MPL_AUX_LAMBDA_SUPPORT(
|
||||||
|
4,set_factory_class,(Entry,Key,Compare,Allocator))
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||||
|
/* This is preferred to deriving from factory_marker since checking for
|
||||||
|
* derivation forces the instantiation of the specifier, which is not
|
||||||
|
* needed when the specifier is a placeholder expression.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Entry,typename Key,
|
||||||
|
typename Compare,typename Allocator
|
||||||
|
>
|
||||||
|
struct is_factory<set_factory_class<Entry,Key,Compare,Allocator> >:
|
||||||
|
boost::mpl::true_{};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* set_factory_class specifier */
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Compare,typename Allocator
|
||||||
|
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION_DEF
|
||||||
|
>
|
||||||
|
struct set_factory:factory_marker
|
||||||
|
{
|
||||||
|
template<typename Entry,typename Key>
|
||||||
|
struct apply:
|
||||||
|
mpl::apply2<
|
||||||
|
set_factory_class<
|
||||||
|
boost::mpl::_1,boost::mpl::_2,Compare,Allocator
|
||||||
|
>,
|
||||||
|
Entry,Key
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
40
include/boost/flyweight/set_factory_fwd.hpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_SET_FACTORY_FWD_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_SET_FACTORY_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/detail/not_placeholder_expr.hpp>
|
||||||
|
#include <boost/mpl/aux_/na.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Entry,typename Key,
|
||||||
|
typename Compare=mpl::na,typename Allocator=mpl::na
|
||||||
|
>
|
||||||
|
class set_factory_class;
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Compare=mpl::na,typename Allocator=mpl::na
|
||||||
|
BOOST_FLYWEIGHT_NOT_A_PLACEHOLDER_EXPRESSION
|
||||||
|
>
|
||||||
|
struct set_factory;
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
37
include/boost/flyweight/simple_locking.hpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_SIMPLE_LOCKING_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_SIMPLE_LOCKING_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/detail/recursive_lw_mutex.hpp>
|
||||||
|
#include <boost/flyweight/simple_locking_fwd.hpp>
|
||||||
|
#include <boost/flyweight/locking_tag.hpp>
|
||||||
|
|
||||||
|
/* simple locking policy based on native recursive mutexes */
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
struct simple_locking:locking_marker
|
||||||
|
{
|
||||||
|
typedef detail::recursive_lightweight_mutex mutex_type;
|
||||||
|
typedef mutex_type::scoped_lock lock_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
26
include/boost/flyweight/simple_locking_fwd.hpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_SIMPLE_LOCKING_FWD_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_SIMPLE_LOCKING_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
struct simple_locking;
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
66
include/boost/flyweight/static_holder.hpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_STATIC_HOLDER_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_STATIC_HOLDER_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/static_holder_fwd.hpp>
|
||||||
|
#include <boost/flyweight/holder_tag.hpp>
|
||||||
|
#include <boost/mpl/aux_/lambda_support.hpp>
|
||||||
|
|
||||||
|
/* Simplest holder storing the T object as a local static variable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
struct static_holder_class:holder_marker
|
||||||
|
{
|
||||||
|
static C& get()
|
||||||
|
{
|
||||||
|
static C c;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef static_holder_class type;
|
||||||
|
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,static_holder_class,(C))
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||||
|
/* This is preferred to deriving from holder_marker since checking for
|
||||||
|
* derivation forces the instantiation of the specifier, which is not
|
||||||
|
* needed when the specifier is a placeholder expression.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
struct is_holder<static_holder_class<C> >:boost::mpl::true_{};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* static_holder_class specifier */
|
||||||
|
|
||||||
|
struct static_holder:holder_marker
|
||||||
|
{
|
||||||
|
template<typename C>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef static_holder_class<C> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
29
include/boost/flyweight/static_holder_fwd.hpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_STATIC_HOLDER_FWD_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_STATIC_HOLDER_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
struct static_holder_class;
|
||||||
|
|
||||||
|
struct static_holder;
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
46
include/boost/flyweight/tag.hpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_TAG_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_TAG_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/parameter/parameters.hpp>
|
||||||
|
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||||
|
|
||||||
|
/* A type T can be used as a tag in the specification of a flyweight
|
||||||
|
* by passing it wrapped in the form tag<T>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
struct tag_marker{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_tag:is_base_and_derived<tag_marker,T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
} /* namespace flyweights::detail */
|
||||||
|
|
||||||
|
template<typename T=parameter::void_>
|
||||||
|
struct tag:parameter::template_keyword<tag<>,T>,detail::tag_marker
|
||||||
|
{};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
44
include/boost/flyweight/tracking_tag.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_TRACKING_TAG_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_TRACKING_TAG_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/parameter/parameters.hpp>
|
||||||
|
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace flyweights{
|
||||||
|
|
||||||
|
/* Three ways to indicate that a given class T is a tracking policy:
|
||||||
|
* 1. Make it derived from tracking_marker.
|
||||||
|
* 2. Specialize is_tracking to evaluate to boost::mpl::true_.
|
||||||
|
* 3. Pass it as tracking<T> when defining a flyweight type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct tracking_marker{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_tracking:is_base_and_derived<tracking_marker,T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename T=parameter::void_>
|
||||||
|
struct tracking:parameter::template_keyword<tracking<>,T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
} /* namespace flyweights */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
20
index.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||||
|
<!--
|
||||||
|
Copyright 2006 Joaquín M López Muñoz.
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<meta http-equiv="refresh" content="0; URL=doc/index.html">
|
||||||
|
<title>Boost.Flyweight Documentation</title>
|
||||||
|
<link rel="stylesheet" href="doc/style.css" type="text/css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
Automatic redirection failed, please go to
|
||||||
|
<a href="doc/index.html">doc/index.html</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
34
test/Jamfile.v2
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Boost.Flyweight tests Jamfile
|
||||||
|
#
|
||||||
|
# Copyright 2006-2008 Joaquín M López Muñoz.
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
#
|
||||||
|
# See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
|
||||||
|
project
|
||||||
|
: requirements
|
||||||
|
<os>LINUX:<threading>multi
|
||||||
|
;
|
||||||
|
|
||||||
|
test-suite "flyweight" :
|
||||||
|
[ run test_assoc_cont_factory.cpp test_assoc_cont_fact_main.cpp ]
|
||||||
|
[ run test_basic.cpp test_basic_main.cpp ]
|
||||||
|
[ run test_custom_factory.cpp test_custom_factory_main.cpp ]
|
||||||
|
[ run test_init.cpp test_init_main.cpp ]
|
||||||
|
[ run test_intermod_holder.cpp test_intermod_holder_main.cpp
|
||||||
|
intermod_holder_dll
|
||||||
|
: # command line
|
||||||
|
: # input files
|
||||||
|
: # requirements
|
||||||
|
<threading>multi ]
|
||||||
|
[ run test_multictor.cpp test_multictor_main.cpp ]
|
||||||
|
[ run test_no_locking.cpp test_no_locking_main.cpp ]
|
||||||
|
[ run test_no_tracking.cpp test_no_tracking_main.cpp ]
|
||||||
|
[ run test_set_factory.cpp test_set_factory_main.cpp ]
|
||||||
|
;
|
||||||
|
|
||||||
|
lib intermod_holder_dll : intermod_holder_dll.cpp :
|
||||||
|
<link>shared
|
||||||
|
<define>BOOST_FLYWEIGHT_TEST_INTERMOD_HOLDER_DLL_SOURCE=1 ;
|
||||||
87
test/heavy_objects.hpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/* Boost.Flyweight basic test template.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_TEST_HEAVY_OBJECTS_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_TEST_HEAVY_OBJECTS_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct texture
|
||||||
|
{
|
||||||
|
texture(const std::string& str=""):str(str){}
|
||||||
|
|
||||||
|
friend bool operator==(
|
||||||
|
const texture& x,const texture& y){return x.str==y.str;}
|
||||||
|
friend bool operator< (
|
||||||
|
const texture& x,const texture& y){return x.str< y.str;}
|
||||||
|
friend bool operator!=(
|
||||||
|
const texture& x,const texture& y){return x.str!=y.str;}
|
||||||
|
friend bool operator> (
|
||||||
|
const texture& x,const texture& y){return x.str> y.str;}
|
||||||
|
friend bool operator>=(
|
||||||
|
const texture& x,const texture& y){return x.str>=y.str;}
|
||||||
|
friend bool operator<=(
|
||||||
|
const texture& x,const texture& y){return x.str<=y.str;}
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& os,const texture& x)
|
||||||
|
{
|
||||||
|
return os<<x.str;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::istream& operator>>(std::istream& is,texture& x)
|
||||||
|
{
|
||||||
|
return is>>x.str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string str;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct from_texture_to_string
|
||||||
|
{
|
||||||
|
const std::string& operator()(const texture& x)const{return x.str;}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct factorization:private boost::noncopyable
|
||||||
|
{
|
||||||
|
factorization(int n=0):n(n){}
|
||||||
|
|
||||||
|
friend bool operator==(
|
||||||
|
const factorization& x,const factorization& y){return x.n==y.n;}
|
||||||
|
friend bool operator< (
|
||||||
|
const factorization& x,const factorization& y){return x.n< y.n;}
|
||||||
|
friend bool operator!=(
|
||||||
|
const factorization& x,const factorization& y){return x.n!=y.n;}
|
||||||
|
friend bool operator> (
|
||||||
|
const factorization& x,const factorization& y){return x.n> y.n;}
|
||||||
|
friend bool operator>=(
|
||||||
|
const factorization& x,const factorization& y){return x.n>=y.n;}
|
||||||
|
friend bool operator<=(
|
||||||
|
const factorization& x,const factorization& y){return x.n<=y.n;}
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& os,const factorization& x)
|
||||||
|
{
|
||||||
|
return os<<x.n;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::istream& operator>>(std::istream& is,factorization& x)
|
||||||
|
{
|
||||||
|
return is>>x.n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
17
test/intermod_holder_dll.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/* Boost.Flyweight test of intermodule_holder.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "intermod_holder_dll.hpp"
|
||||||
|
|
||||||
|
intermodule_flyweight_string create_intermodule_flyweight_string(
|
||||||
|
const std::string& str)
|
||||||
|
{
|
||||||
|
return intermodule_flyweight_string(str);
|
||||||
|
}
|
||||||
45
test/intermod_holder_dll.hpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/* Boost.Flyweight test of intermodule_holder.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_TEST_INTERMOD_HOLDER_DLL_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_TEST_INTERMOD_HOLDER_DLL_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/flyweight.hpp>
|
||||||
|
#include <boost/flyweight/hashed_factory.hpp>
|
||||||
|
#include <boost/flyweight/intermodule_holder.hpp>
|
||||||
|
#include <boost/flyweight/refcounted.hpp>
|
||||||
|
#include <boost/flyweight/simple_locking.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef BOOST_HAS_DECLSPEC
|
||||||
|
#ifdef BOOST_FLYWEIGHT_TEST_INTERMOD_HOLDER_DLL_SOURCE
|
||||||
|
#define BOOST_FLYWEIGHT_DLL_DECL __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define BOOST_FLYWEIGHT_DLL_DECL __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define BOOST_FLYWEIGHT_DLL_DECL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef boost::flyweights::flyweight<
|
||||||
|
std::string,
|
||||||
|
boost::flyweights::intermodule_holder> intermodule_flyweight_string;
|
||||||
|
|
||||||
|
BOOST_FLYWEIGHT_DLL_DECL intermodule_flyweight_string
|
||||||
|
create_intermodule_flyweight_string(const std::string&);
|
||||||
|
|
||||||
|
#undef BOOST_FLYWEIGHT_DLL_DECL
|
||||||
|
|
||||||
|
#endif
|
||||||
36
test/test_all_main.cpp
Normal file
@@ -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();
|
||||||
|
}
|
||||||
18
test/test_assoc_cont_fact_main.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/* Boost.Flyweight test of assoc_container_factory.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include "test_assoc_cont_factory.hpp"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test_assoc_container_factory();
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
||||||
68
test/test_assoc_cont_factory.cpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/* Boost.Flyweight test of assoc_container_factory.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_assoc_cont_factory.hpp"
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/assoc_container_factory.hpp>
|
||||||
|
#include <boost/flyweight/flyweight.hpp>
|
||||||
|
#include <boost/flyweight/refcounted.hpp>
|
||||||
|
#include <boost/flyweight/simple_locking.hpp>
|
||||||
|
#include <boost/flyweight/static_holder.hpp>
|
||||||
|
#include <functional>
|
||||||
|
#include <set>
|
||||||
|
#include "test_basic_template.hpp"
|
||||||
|
|
||||||
|
using namespace boost::flyweights;
|
||||||
|
|
||||||
|
struct reverse_set_specifier
|
||||||
|
{
|
||||||
|
template<typename Entry,typename Key>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef std::set<Entry,std::greater<Key> > type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct assoc_container_factory_flyweight_specifier1
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef flyweight<
|
||||||
|
T,
|
||||||
|
assoc_container_factory<reverse_set_specifier>
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct assoc_container_factory_flyweight_specifier2
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef flyweight<
|
||||||
|
T,
|
||||||
|
assoc_container_factory_class<
|
||||||
|
std::set<
|
||||||
|
boost::mpl::_1,
|
||||||
|
std::greater<boost::mpl::_2>,
|
||||||
|
std::allocator<boost::mpl::_1>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_assoc_container_factory()
|
||||||
|
{
|
||||||
|
test_basic_template<assoc_container_factory_flyweight_specifier1>();
|
||||||
|
test_basic_template<assoc_container_factory_flyweight_specifier2>();
|
||||||
|
}
|
||||||
11
test/test_assoc_cont_factory.hpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/* Boost.Flyweight test of assoc_container_factory.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void test_assoc_container_factory();
|
||||||
68
test/test_basic.cpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/* Boost.Flyweight basic test.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_basic.hpp"
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight.hpp>
|
||||||
|
#include "test_basic_template.hpp"
|
||||||
|
|
||||||
|
using namespace boost::flyweights;
|
||||||
|
|
||||||
|
struct basic_flyweight_specifier1
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef flyweight<T> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct basic_flyweight_specifier2
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef flyweight<
|
||||||
|
T,tag<int>,
|
||||||
|
static_holder_class<boost::mpl::_1>,
|
||||||
|
hashed_factory_class<
|
||||||
|
boost::mpl::_1,boost::mpl::_2,
|
||||||
|
boost::hash<boost::mpl::_2>,std::equal_to<boost::mpl::_2>,
|
||||||
|
std::allocator<boost::mpl::_1>
|
||||||
|
>,
|
||||||
|
simple_locking,
|
||||||
|
refcounted
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct basic_flyweight_specifier3
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef flyweight<
|
||||||
|
T,
|
||||||
|
hashed_factory<
|
||||||
|
boost::hash<boost::mpl::_2>,std::equal_to<boost::mpl::_2>,
|
||||||
|
std::allocator<boost::mpl::_1>
|
||||||
|
>,
|
||||||
|
tag<int>
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_basic()
|
||||||
|
{
|
||||||
|
test_basic_template<basic_flyweight_specifier1>();
|
||||||
|
test_basic_template<basic_flyweight_specifier2>();
|
||||||
|
test_basic_template<basic_flyweight_specifier3>();
|
||||||
|
}
|
||||||
11
test/test_basic.hpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/* Boost.Flyweight basic test.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void test_basic();
|
||||||
18
test/test_basic_main.cpp
Normal file
@@ -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();
|
||||||
|
}
|
||||||
232
test/test_basic_template.hpp
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
/* Boost.Flyweight basic test template.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_FLYWEIGHT_TEST_BASIC_TEMPLATE_HPP
|
||||||
|
#define BOOST_FLYWEIGHT_TEST_BASIC_TEMPLATE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/flyweight/key_value.hpp>
|
||||||
|
#include <boost/mpl/apply.hpp>
|
||||||
|
#include <boost/utility/value_init.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include "heavy_objects.hpp"
|
||||||
|
|
||||||
|
#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
|
||||||
|
|
||||||
|
template<typename Flyweight,typename ForwardIterator>
|
||||||
|
void test_basic_template(
|
||||||
|
ForwardIterator first,ForwardIterator last
|
||||||
|
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight))
|
||||||
|
{
|
||||||
|
typedef typename Flyweight::value_type value_type;
|
||||||
|
|
||||||
|
ForwardIterator it;
|
||||||
|
|
||||||
|
for(it=first;it!=last;++it){
|
||||||
|
/* construct/copy/destroy */
|
||||||
|
|
||||||
|
Flyweight f1(*it);
|
||||||
|
Flyweight f2;
|
||||||
|
Flyweight c1(f1);
|
||||||
|
Flyweight c2(static_cast<const Flyweight&>(f2));
|
||||||
|
value_type v1(*it);
|
||||||
|
boost::value_initialized<value_type> v2;
|
||||||
|
BOOST_TEST(f1.get_key()==*it);
|
||||||
|
BOOST_TEST((f1==f2)==(f1.get()==v2.data()));
|
||||||
|
BOOST_TEST(f1==c1);
|
||||||
|
BOOST_TEST(f2==c2);
|
||||||
|
|
||||||
|
f1=f1;
|
||||||
|
BOOST_TEST(f1==f1);
|
||||||
|
|
||||||
|
c1=f2;
|
||||||
|
BOOST_TEST(c1==f2);
|
||||||
|
|
||||||
|
c1=f1;
|
||||||
|
BOOST_TEST(c1==f1);
|
||||||
|
|
||||||
|
/* convertibility to underlying type */
|
||||||
|
|
||||||
|
BOOST_TEST(f1.get()==v1);
|
||||||
|
|
||||||
|
/* identity of reference */
|
||||||
|
|
||||||
|
BOOST_TEST(&f1.get()==&c1.get());
|
||||||
|
|
||||||
|
/* modifiers */
|
||||||
|
|
||||||
|
f1.swap(f1);
|
||||||
|
BOOST_TEST(f1==c1);
|
||||||
|
|
||||||
|
f1.swap(f2);
|
||||||
|
BOOST_TEST(f1==c2);
|
||||||
|
BOOST_TEST(f2==c1);
|
||||||
|
|
||||||
|
boost::flyweights::swap(f1,f2);
|
||||||
|
BOOST_TEST(f1==c1);
|
||||||
|
BOOST_TEST(f2==c2);
|
||||||
|
|
||||||
|
/* specialized algorithms */
|
||||||
|
|
||||||
|
std::ostringstream oss1;
|
||||||
|
oss1<<f1;
|
||||||
|
std::ostringstream oss2;
|
||||||
|
oss2<<f1.get();
|
||||||
|
BOOST_TEST(oss1.str()==oss2.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Flyweight,typename ForwardIterator>
|
||||||
|
void test_basic_with_assign_template(
|
||||||
|
ForwardIterator first,ForwardIterator last
|
||||||
|
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight))
|
||||||
|
{
|
||||||
|
typedef typename Flyweight::value_type value_type;
|
||||||
|
|
||||||
|
ForwardIterator it;
|
||||||
|
|
||||||
|
test_basic_template<Flyweight>(first,last);
|
||||||
|
|
||||||
|
for(it=first;it!=last;++it){
|
||||||
|
/* value construction */
|
||||||
|
|
||||||
|
value_type v(*it);
|
||||||
|
Flyweight f1(v);
|
||||||
|
Flyweight f2(f1.get());
|
||||||
|
BOOST_TEST(f1.get()==v);
|
||||||
|
BOOST_TEST(f2.get()==v);
|
||||||
|
BOOST_TEST(f1==f2);
|
||||||
|
|
||||||
|
/* value assignment */
|
||||||
|
|
||||||
|
Flyweight f3,f4;
|
||||||
|
f3=v;
|
||||||
|
f4=f1.get();
|
||||||
|
BOOST_TEST(f2.get()==v);
|
||||||
|
BOOST_TEST(f3.get()==v);
|
||||||
|
BOOST_TEST(f2==f3);
|
||||||
|
|
||||||
|
/* specialized algorithms */
|
||||||
|
|
||||||
|
std::ostringstream oss1;
|
||||||
|
oss1<<f1;
|
||||||
|
std::istringstream iss1(oss1.str());
|
||||||
|
Flyweight f5;
|
||||||
|
iss1>>f5;
|
||||||
|
BOOST_TEST(f5==f1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Flyweight1,typename Flyweight2,
|
||||||
|
typename ForwardIterator1,typename ForwardIterator2
|
||||||
|
>
|
||||||
|
void test_basic_comparison_template(
|
||||||
|
ForwardIterator1 first1,ForwardIterator1 last1,
|
||||||
|
ForwardIterator2 first2
|
||||||
|
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight1)
|
||||||
|
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight2))
|
||||||
|
{
|
||||||
|
typedef typename Flyweight1::value_type value_type1;
|
||||||
|
typedef typename Flyweight2::value_type value_type2;
|
||||||
|
|
||||||
|
for(;first1!=last1;++first1,++first2){
|
||||||
|
value_type1 v1=value_type1(*first1);
|
||||||
|
value_type2 v2=value_type2(*first2);
|
||||||
|
Flyweight1 f1(v1);
|
||||||
|
Flyweight2 f2(v2);
|
||||||
|
|
||||||
|
BOOST_TEST((f1==f2)==(f1.get()==v2));
|
||||||
|
BOOST_TEST((f1< f2)==(f1.get()< v2));
|
||||||
|
BOOST_TEST((f1!=f2)==(f1.get()!=v2));
|
||||||
|
BOOST_TEST((f1> f2)==(f1.get()> v2));
|
||||||
|
BOOST_TEST((f1>=f2)==(f1.get()>=v2));
|
||||||
|
BOOST_TEST((f1<=f2)==(f1.get()<=v2));
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||||
|
BOOST_TEST((f1==v2)==(f1.get()==v2));
|
||||||
|
BOOST_TEST((f1< v2)==(f1.get()< v2));
|
||||||
|
BOOST_TEST((f1!=v2)==(f1.get()!=v2));
|
||||||
|
BOOST_TEST((f1> v2)==(f1.get()> v2));
|
||||||
|
BOOST_TEST((f1>=v2)==(f1.get()>=v2));
|
||||||
|
BOOST_TEST((f1<=v2)==(f1.get()<=v2));
|
||||||
|
|
||||||
|
BOOST_TEST((v1==f2)==(f1.get()==v2));
|
||||||
|
BOOST_TEST((v1< f2)==(f1.get()< v2));
|
||||||
|
BOOST_TEST((v1!=f2)==(f1.get()!=v2));
|
||||||
|
BOOST_TEST((v1> f2)==(f1.get()> v2));
|
||||||
|
BOOST_TEST((v1>=f2)==(f1.get()>=v2));
|
||||||
|
BOOST_TEST((v1<=f2)==(f1.get()<=v2));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FlyweightSpecifier>
|
||||||
|
void test_basic_template(BOOST_EXPLICIT_TEMPLATE_TYPE(FlyweightSpecifier))
|
||||||
|
{
|
||||||
|
typedef typename boost::mpl::apply1<
|
||||||
|
FlyweightSpecifier,int
|
||||||
|
>::type int_flyweight;
|
||||||
|
|
||||||
|
typedef typename boost::mpl::apply1<
|
||||||
|
FlyweightSpecifier,std::string
|
||||||
|
>::type string_flyweight;
|
||||||
|
|
||||||
|
typedef typename boost::mpl::apply1<
|
||||||
|
FlyweightSpecifier,char
|
||||||
|
>::type char_flyweight;
|
||||||
|
|
||||||
|
typedef typename boost::mpl::apply1<
|
||||||
|
FlyweightSpecifier,
|
||||||
|
boost::flyweights::key_value<std::string,texture,from_texture_to_string>
|
||||||
|
>::type texture_flyweight;
|
||||||
|
|
||||||
|
typedef typename boost::mpl::apply1<
|
||||||
|
FlyweightSpecifier,
|
||||||
|
boost::flyweights::key_value<int,factorization>
|
||||||
|
>::type factorization_flyweight;
|
||||||
|
|
||||||
|
int ints[]={0,1,1,0,1,2,3,4,3,4,0,0};
|
||||||
|
test_basic_with_assign_template<int_flyweight>(
|
||||||
|
&ints[0],&ints[0]+LENGTHOF(ints));
|
||||||
|
|
||||||
|
const char* words[]={"hello","boost","flyweight","boost","bye","c++","c++"};
|
||||||
|
test_basic_with_assign_template<string_flyweight>(
|
||||||
|
&words[0],&words[0]+LENGTHOF(words));
|
||||||
|
|
||||||
|
const char* textures[]={"wood","grass","sand","granite","terracotta"};
|
||||||
|
test_basic_with_assign_template<texture_flyweight>(
|
||||||
|
&textures[0],&textures[0]+LENGTHOF(textures));
|
||||||
|
|
||||||
|
int factorizations[]={1098,102387,90846,2223978};
|
||||||
|
test_basic_template<factorization_flyweight>(
|
||||||
|
&factorizations[0],&factorizations[0]+LENGTHOF(factorizations));
|
||||||
|
|
||||||
|
char chars[]={0,2,4,5,1,1,1,3,4,1,1,0};
|
||||||
|
test_basic_comparison_template<int_flyweight,char_flyweight>(
|
||||||
|
&ints[0],&ints[0]+LENGTHOF(ints),&chars[0]);
|
||||||
|
|
||||||
|
test_basic_comparison_template<string_flyweight,string_flyweight>(
|
||||||
|
&words[0],&words[0]+LENGTHOF(words)-1,&words[1]);
|
||||||
|
|
||||||
|
test_basic_comparison_template<texture_flyweight,texture_flyweight>(
|
||||||
|
&textures[0],&textures[0]+LENGTHOF(textures)-1,&textures[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef LENGTHOF
|
||||||
|
|
||||||
|
#endif
|
||||||
111
test/test_custom_factory.cpp
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/* Boost.Flyweight test of a custom factory.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_custom_factory.hpp"
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/flyweight/flyweight.hpp>
|
||||||
|
#include <boost/flyweight/refcounted.hpp>
|
||||||
|
#include <boost/flyweight/simple_locking.hpp>
|
||||||
|
#include <boost/flyweight/static_holder.hpp>
|
||||||
|
#include <boost/mpl/aux_/lambda_support.hpp>
|
||||||
|
#include <list>
|
||||||
|
#include "test_basic_template.hpp"
|
||||||
|
|
||||||
|
using namespace boost::flyweights;
|
||||||
|
|
||||||
|
/* Info on list-update containers:
|
||||||
|
* http://gcc.gnu.org/onlinedocs/libstdc++/ext/pb_ds/lu_based_containers.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename Entry,typename Key>
|
||||||
|
class lu_factory_class:public factory_marker
|
||||||
|
{
|
||||||
|
struct entry_type
|
||||||
|
{
|
||||||
|
entry_type(const Entry& x_):x(x_),count(0){}
|
||||||
|
|
||||||
|
Entry x;
|
||||||
|
std::size_t count;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::list<entry_type> container_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename container_type::iterator handle_type;
|
||||||
|
|
||||||
|
handle_type insert(const Entry& x)
|
||||||
|
{
|
||||||
|
handle_type h;
|
||||||
|
for(h=cont.begin();h!=cont.end();++h){
|
||||||
|
if(static_cast<const Key&>(h->x)==static_cast<const Key&>(x)){
|
||||||
|
if(++(h->count)==10){
|
||||||
|
h->count=0;
|
||||||
|
cont.splice(cont.begin(),cont,h); /* move to front */
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cont.push_back(entry_type(x));
|
||||||
|
h=cont.end();
|
||||||
|
--h;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase(handle_type h)
|
||||||
|
{
|
||||||
|
cont.erase(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Entry& entry(handle_type h){return h->x;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
container_type cont;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef lu_factory_class type;
|
||||||
|
BOOST_MPL_AUX_LAMBDA_SUPPORT(2,lu_factory_class,(Entry,Key))
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lu_factory:factory_marker
|
||||||
|
{
|
||||||
|
template<typename Entry,typename Key>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef lu_factory_class<Entry,Key> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct custom_factory_flyweight_specifier1
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef flyweight<T,lu_factory> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct custom_factory_flyweight_specifier2
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef flyweight<
|
||||||
|
T,
|
||||||
|
lu_factory_class<boost::mpl::_1,boost::mpl::_2>
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_custom_factory()
|
||||||
|
{
|
||||||
|
test_basic_template<custom_factory_flyweight_specifier1>();
|
||||||
|
test_basic_template<custom_factory_flyweight_specifier2>();
|
||||||
|
}
|
||||||
11
test/test_custom_factory.hpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/* Boost.Flyweight test of a custom factory.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void test_custom_factory();
|
||||||
18
test/test_custom_factory_main.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/* Boost.Flyweight test of a custom factory.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include "test_custom_factory.hpp"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test_custom_factory();
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
||||||
47
test/test_init.cpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/* Boost.Flyweight test of static data initialization facilities.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_init.hpp"
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/flyweight.hpp>
|
||||||
|
|
||||||
|
using namespace boost::flyweights;
|
||||||
|
|
||||||
|
template<bool* pmark,typename Entry,typename Value>
|
||||||
|
struct marked_hashed_factory_class:hashed_factory_class<Entry,Value>
|
||||||
|
{
|
||||||
|
marked_hashed_factory_class(){*pmark=true;}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<bool* pmark>
|
||||||
|
struct marked_hashed_factory:factory_marker
|
||||||
|
{
|
||||||
|
template<typename Entry,typename Value>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef marked_hashed_factory_class<pmark,Entry,Value> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace{
|
||||||
|
bool mark1=false;
|
||||||
|
bool init1=flyweight<int,marked_hashed_factory<&mark1> >::init();
|
||||||
|
|
||||||
|
bool mark2=false;
|
||||||
|
flyweight<int,marked_hashed_factory<&mark2> >::initializer init2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_init()
|
||||||
|
{
|
||||||
|
BOOST_TEST(mark1);
|
||||||
|
BOOST_TEST(mark2);
|
||||||
|
}
|
||||||
11
test/test_init.hpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/* Boost.Flyweight test of static data initialization facilities.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void test_init();
|
||||||
18
test/test_init_main.cpp
Normal file
@@ -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();
|
||||||
|
}
|
||||||
34
test/test_intermod_holder.cpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/* Boost.Flyweight test of intermodule_holder.
|
||||||
|
*
|
||||||
|
* Copyright 2006-2008 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/flyweight for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_intermod_holder.hpp"
|
||||||
|
|
||||||
|
#include "intermod_holder_dll.hpp"
|
||||||
|
#include "test_basic_template.hpp"
|
||||||
|
|
||||||
|
using namespace boost::flyweights;
|
||||||
|
|
||||||
|
struct intermodule_holder_flyweight_specifier1
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef flyweight<T,intermodule_holder> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_intermodule_holder()
|
||||||
|
{
|
||||||
|
test_basic_template<intermodule_holder_flyweight_specifier1>();
|
||||||
|
|
||||||
|
intermodule_flyweight_string str=
|
||||||
|
create_intermodule_flyweight_string("boost");
|
||||||
|
BOOST_TEST(str==intermodule_flyweight_string("boost"));
|
||||||
|
}
|
||||||