• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
2
3<html>
4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
6<title>Boost.Flyweight Documentation - Tutorial - Basics</title>
7<link rel="stylesheet" href="../style.css" type="text/css">
8<link rel="start" href="../index.html">
9<link rel="prev" href="index.html">
10<link rel="up" href="index.html">
11<link rel="next" href="key_value.html">
12</head>
13
14<body>
15<h1><img src="../../../../boost.png" alt="Boost logo" align=
16"middle" width="277" height="86">Boost.Flyweight Tutorial: Basics</h1>
17
18<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.Flyweight tutorial" border="0"><br>
19Boost.Flyweight tutorial
20</a></div>
21<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br>
22Boost.Flyweight tutorial
23</a></div>
24<div class="next_link"><a href="key_value.html"><img src="../next.gif" alt="key-value flyweights" border="0"><br>
25Key-value flyweights
26</a></div><br clear="all" style="clear: all;">
27
28<hr>
29
30<h2>Contents</h2>
31
32<ul>
33  <li><a href="#intro">Introduction</a>
34    <ul>
35      <li><a href="#serialization">Serialization</a></li>
36    </ul>
37  </li>
38  <li><a href="#requirements">Flyweight requirements</a></li>
39</ul>
40
41<h2><a name="intro">Introduction</a></h2>
42
43<p>
44Suppose we are writing a massive multiplayer online game
45which has to maintain hundreds of thousands or millions of instances
46of the following class in memory:
47</p>
48
49<blockquote><pre>
50<span class=keyword>struct</span> <span class=identifier>user_entry</span>
51<span class=special>{</span>
52  <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>first_name</span><span class=special>;</span>
53  <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>last_name</span><span class=special>;</span>
54  <span class=keyword>int</span>         <span class=identifier>age</span><span class=special>;</span>
55  <span class=special>...</span>
56<span class=special>};</span>
57</pre></blockquote>
58
59<p>
60In this kind of environments memory resources are precious, so we are seeking
61ways to make <code>user_entry</code> as compact as possible. Typically, there
62exists a very high level of repetition of first and last names among
63the community users, so an obvious optimization consists in moving
64<code>user_entry::first_name</code> and <code>user_entry::last_name</code>
65objects to a common repository where duplicates are avoided, and leaving
66references to these inside <code>user_entry</code>. This is precisely what
67Boost.Flyweight does in the simplest possible way for the programmer:
68</p>
69
70<blockquote><pre>
71<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
72
73<span class=keyword>struct</span> <span class=identifier>user_entry</span>
74<span class=special>{</span>
75  <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=identifier>first_name</span><span class=special>;</span>
76  <span class=identifier>flyweight</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=identifier>last_name</span><span class=special>;</span>
77  <span class=keyword>int</span>                    <span class=identifier>age</span><span class=special>;</span>
78  <span class=special>...</span>
79<span class=special>};</span>
80</pre></blockquote>
81
82<p>
83Boost.Flyweight automatically performs the optimization just described behind
84the scenes, so that the net effect of this change is that the memory
85usage of the program decreases by a factor proportional to the level of
86redundancy among user names.
87</p>
88
89<p>
90<code>flyweight&lt;std::string&gt;</code> behaves in many ways like
91<code>std::string</code>; for instance, the following code works
92unchanged after the redefinition of <code>user_entry</code>:
93</p>
94
95<blockquote><pre>
96<span class=comment>// flyweight&lt;T&gt; can be constructed in the same way as T objects can,
97// even with multiple argument constructors</span>
98
99<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>
100  <span class=identifier>first_name</span><span class=special>(</span><span class=identifier>f</span><span class=special>),</span>
101  <span class=identifier>last_name</span><span class=special>(</span><span class=identifier>l</span><span class=special>),</span>
102  <span class=identifier>age</span><span class=special>(</span><span class=identifier>a</span><span class=special>),</span>
103  <span class=special>...</span>
104<span class=special>{}</span>
105
106<span class=comment>// flyweight classes have relational operators replicating the
107// semantics of the underyling type</span>
108
109<span class=keyword>bool</span> <span class=identifier>same_name</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user1</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user2</span><span class=special>)</span>
110<span class=special>{</span>
111  <span class=keyword>return</span> <span class=identifier>user1</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>==</span><span class=identifier>user2</span><span class=special>.</span><span class=identifier>first_name</span> <span class=special>&amp;&amp;</span>
112         <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>
113<span class=special>}</span>
114
115<span class=comment>// flyweight&lt;T&gt; provides operator&lt;&lt; and operator&gt;&gt; internally
116// forwarding to T::operator&lt;&lt; and T::operator&gt;&gt;</span>
117
118<span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>&lt;&lt;(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream</span><span class=special>&amp;</span> <span class=identifier>os</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user</span><span class=special>)</span>
119<span class=special>{</span>
120  <span class=keyword>return</span> <span class=identifier>os</span><span class=special>&lt;&lt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>&lt;&lt;</span><span class=string>&quot; &quot;</span><span class=special>&lt;&lt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>&lt;&lt;</span><span class=string>&quot; &quot;</span><span class=special>&lt;&lt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>age</span><span class=special>;</span>
121<span class=special>}</span>
122
123<span class=identifier>std</span><span class=special>::</span><span class=identifier>istream</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>&gt;&gt;(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>istream</span><span class=special>&amp;</span> <span class=identifier>is</span><span class=special>,</span><span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user</span><span class=special>)</span>
124<span class=special>{</span>
125  <span class=keyword>return</span> <span class=identifier>is</span><span class=special>&gt;&gt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>&gt;&gt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>&gt;&gt;</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>age</span><span class=special>;</span>
126<span class=special>}</span>
127</pre></blockquote>
128
129<p>
130Besides, <code>flyweight&lt;T&gt;</code> is convertible to
131<code>const T&amp;</code>, either implicitly or through the <code>get</code>
132member function:
133</p>
134
135<blockquote><pre>
136<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>full_name</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user</span><span class=special>)</span>
137<span class=special>{</span>
138  <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>full</span><span class=special>;</span>
139
140  <span class=identifier>full</span><span class=special>.</span><span class=identifier>reserve</span><span class=special>(</span>
141    <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>
142    <span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>.</span><span class=identifier>get</span><span class=special>().</span><span class=identifier>size</span><span class=special>()+</span><span class=number>1</span><span class=special>);</span> <span class=comment>// const std::string&amp;</span>
143
144  <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>
145  <span class=identifier>full</span><span class=special>+=</span><span class=string>&quot; &quot;</span><span class=special>;</span>
146  <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>
147
148  <span class=keyword>return</span> <span class=identifier>full</span><span class=special>;</span>
149<span class=special>}</span>
150</pre></blockquote>
151
152<p>
153The most important restriction to take into account when replacing a class
154with an equivalent flyweight is the fact that flyweights are not
155mutable: since several flyweight objects can share the same representation
156value, modifying this value is not admissible. On the other hand, flyweight
157objects can be assigned new values:
158</p>
159
160<blockquote><pre>
161<span class=keyword>void</span> <span class=identifier>change_name</span><span class=special>(</span>
162  <span class=identifier>user_entry</span><span class=special>&amp;</span> <span class=identifier>user</span><span class=special>,</span>
163  <span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=identifier>f</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=identifier>l</span><span class=special>)</span>
164<span class=special>{</span>
165  <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>
166  <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>
167<span class=special>}</span>
168</pre></blockquote>
169
170<p>
171In general, <code>flyweight&lt;T&gt;</code> interface is designed to make
172the transition from plain <code>T</code> as straightforward as possible.
173Check the <a href="../reference/flyweight.html#flyweight">reference</a> for
174further details on the interface of the class template <code>flyweight</code>.
175The <a href="../examples.html">examples section</a> explores
176some common usage scenarios of Boost.Flyweight.
177</p>
178
179<h4><a name="serialization">Serialization</a></h4>
180
181<p>
182<code>flyweight&lt;T&gt;</code> can be serialized by means of the
183<a href="../../../serialization/index.html">Boost Serialization Library</a>
184as long as the underlying <code>T</code> is serializable. Both regular and
185XML archives are supported. In order to
186use Boost.Flyweight serialization capabilities, the specific
187header <a href="../reference/flyweight.html#serialize_synopsis"><code>"boost/flyweight/serialize.hpp"</code></a>
188must be included.
189</p>
190
191<blockquote><pre><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">flyweight</span><span class="special">/</span><span class="identifier">serialize</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
192
193<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Archive</span><span class="special">&gt;</span>
194<span class="keyword">void</span> <span class="identifier">serialize</span><span class="special">(</span><span class="identifier">Archive</span><span class="special">&amp;</span> <span class="identifier">ar</span><span class="special">,</span><span class="identifier">user_entry</span><span class="special">&amp;</span> <span class="identifier">user</span><span class="special">,</span><span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">int</span><span class="special">)</span>
195<span class="special">{</span>
196  <span class="identifier">ar</span><span class="special">&amp;</span><span class="identifier">user</span><span class="special">.</span><span class="identifier">first_name</span><span class="special">;</span>
197  <span class="identifier">ar</span><span class="special">&amp;</span><span class="identifier">user</span><span class="special">.</span><span class="identifier">last_name</span><span class="special">;</span>
198  <span class="identifier">ar</span><span class="special">&amp;</span><span class="identifier">user</span><span class="special">.</span><span class="identifier">age</span><span class="special">;</span>
199  <span class="special">...</span>
200<span class="special">}</span>
201</pre></blockquote>
202
203<p>
204Much as using Boost.Flyweight reduces memory consumption due to the internal
205sharing of duplicate values, serializing <code>flyweight</code>s can also
206result in smaller archive files, as a common value is only stored
207once and their associated <code>flyweight</code>s get saved as references to it.
208This policy is observed even if <code>flyweight</code> underlying type is
209not <a href="../../../serialization/doc/traits.html#tracking">tracked</a>
210by Boost.Serialization.
211</p>
212
213<p>
214See <a href="../examples.html#example6">example 6</a> at the examples section
215for an illustration of use of Boost.Flyweight serialization capabilities.
216</p>
217
218<h3><a name="requirements">Flyweight requirements</a></h3>
219
220<p>
221For <code>flyweight&lt;T&gt;</code> to be instantiable, <code>T</code> must
222be <a href="https://boost.org/sgi/stl/Assignable.html"><code>Assignable</code></a>,
223<a href="https://boost.org/sgi/stl/EqualityComparable.html"><code>Equality
224Comparable</code></a> and must interoperate with
225<a href="../../../functional/hash/index.html">Boost.Hash</a>.
226The first requirement is probably met without any extra effort by the user,
227not so the other two, except for the most common basic types of C++
228and the standard library. Equality and hashing of <code>T</code> are used
229internally by <code>flyweight&lt;T&gt;</code> internal factory to maintain the
230common repository of unique <code>T</code> values referred to by the flyweight
231objects. Consult the Boost.Hash documentation
232<a href="../../../../doc/html/hash/custom.html">section</a> on extending
233that library for custom data types.
234</p>
235
236<p>
237As we have seen, equality and hash requirements on <code>T</code> are
238imposed by the particular type of <i>flyweight factory</i> internally used by
239<code>flyweight&lt;T&gt;</code>. We will see later how the user can customize
240this factory to use equality and hash predicates other than the default,
241or even switch to an entirely different kind of factory which may impose
242another requirements on <code>T</code>, as described in the section on
243<a href="configuration.html">configuring Boost.Flyweight</a>.
244</p>
245
246<hr>
247
248<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.Flyweight tutorial" border="0"><br>
249Boost.Flyweight tutorial
250</a></div>
251<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br>
252Boost.Flyweight tutorial
253</a></div>
254<div class="next_link"><a href="key_value.html"><img src="../next.gif" alt="key-value flyweights" border="0"><br>
255Key-value flyweights
256</a></div><br clear="all" style="clear: all;">
257
258<br>
259
260<p>Revised April 24th 2019</p>
261
262<p>&copy; Copyright 2006-2019 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
263Distributed under the Boost Software
264License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
265LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
266http://www.boost.org/LICENSE_1_0.txt</a>)
267</p>
268
269</body>
270</html>
271