basics.html 18 KB

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