archive_reference.html 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. <!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  2. <html>
  3. <!--
  4. (C) Copyright 2002-10 Robert Ramey - http://www.rrsd.com .
  5. Use, modification and distribution is subject to the Boost Software
  6. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  7. http://www.boost.org/LICENSE_1_0.txt)
  8. -->
  9. <head>
  10. <meta http-equiv="Content-Type" content="text/html; UTF-8">
  11. <link rel="stylesheet" type="text/css" href="../../../boost.css">
  12. <link rel="stylesheet" type="text/css" href="style.css">
  13. <title>Serialization - More on Archives</title>
  14. </head>
  15. <body link="#0000ff" vlink="#800080">
  16. <table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header">
  17. <tr>
  18. <td valign="top" width="300">
  19. <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../boost.png" border="0"></a></h3>
  20. </td>
  21. <td valign="top">
  22. <h1 align="center">Serialization</h1>
  23. <h2 align="center">Archive Class Reference</h2>
  24. </td>
  25. </tr>
  26. </table>
  27. <hr>
  28. <dl class="page-index">
  29. <dt><a href="#trivial">Trivial Archive</a>
  30. <dt><a href="#implementation">More Useful Archive Classes</a>
  31. <dt><a href="#usage">Usage</a>
  32. <dt><a href="#testing">Testing</a>
  33. <dt><a href="#polymorphic">Polymorphic Archives</a>
  34. </dl>
  35. <h3><a name="trivial">Trivial Archive</a></h3>
  36. The <a href="archives.html"><strong>Archive</strong></a> concept specifies the functions that a
  37. class must implement in order to be used to serialize
  38. <a href="serialization.html"><strong>Serializable</strong></a> types.
  39. Our discussion will focus on archives used for saving as the hierarchy is exactly analogous
  40. for archives used for loading data.
  41. <h4>Minimum Requirments</h4>
  42. The simplest class which will model the <a href="archives.html"><strong>Archive</strong></a> concept specifies the functions that a
  43. class will look like:
  44. <pre><code>
  45. #include &lt;cstddef&gt; // std::size_t
  46. //////////////////////////////////////////////////////////////
  47. // class trivial_oarchive
  48. class trivial_oarchive {
  49. public:
  50. //////////////////////////////////////////////////////////
  51. // public interface used by programs that use the
  52. // serialization library
  53. typedef boost::mpl::bool_&lt;true&gt; is_saving;
  54. typedef boost::mpl::bool_&lt;false&gt; is_loading;
  55. template&lt;class T&gt; void register_type(){}
  56. template&lt;class T&gt; trivial_oarchive & operator&lt;&lt;(const T & t){
  57. return *this;
  58. }
  59. template&lt;class T&gt; trivial_oarchive & operator&(const T & t){
  60. return *this &lt;&lt; t;
  61. }
  62. void save_binary(void *address, std::size_t count){};
  63. };
  64. </code></pre>
  65. The simplest possible input archive class is analogous to the above.
  66. In the following discussion, only output archives will be addressed.
  67. Input archives are exactly symmetrical to output archives.
  68. <p>
  69. This archive will compile and execute with any types which implement the
  70. <a href="serialization.html"><strong>Serializable</strong></a> concept.
  71. For an example see
  72. <a href="../example/demo_trivial_archive.cpp" target="demo_trivial_archive">
  73. <code style="white-space: normal">demo_trivial_archive.cpp</code></a>.
  74. Of course this program won't produce any output as it is. But it provides
  75. the starting point for a simple class which can be used to log formatted
  76. output. See the implementation of a <a href="simple_log.html">simple
  77. log archive</a> to how this has been done.
  78. <h3><a name="implementation">More Useful Archive Classes</a></h3>
  79. The above example is fine as far as it goes. But it doesn't implement
  80. useful features such as serialization of pointers, class versioning
  81. and others. This library implements a family of full featured archive
  82. classes appropriate for a variety of purposes.
  83. <p>
  84. Our archives have been factored into a tree of classes in order to minimize
  85. repetition of code. This is shown in the accompanying
  86. <a target="class_diagram" href="class_diagram.html">class diagram</a>.
  87. Any class which fulfills the following requirements will fit into
  88. this hierarchy and implement all the features we require. Deriving from
  89. the base class <a href="../../../boost/archive/detail/common_oarchive.hpp" target="common_oarchive_hpp">
  90. common_oarchive.hpp</a> provides all features we desire which
  91. are missing from trivial_oarchive above.
  92. <pre><code>
  93. <a href="../../../boost/archive/detail/common_oarchive.hpp" target="common_oarchive_hpp">
  94. #include &lt;cstddef&gt; // std::size_t
  95. #include &lt;boost/archive/detail/common_oarchive.hpp&gt;
  96. </a>
  97. /////////////////////////////////////////////////////////////////////////
  98. // class complete_oarchive
  99. class complete_oarchive :
  100. public boost::archive::detail::common_oarchive&lt;complete_oarchive&gt;
  101. {
  102. // permit serialization system privileged access to permit
  103. // implementation of inline templates for maximum speed.
  104. friend class boost::archive::save_access;
  105. // member template for saving primitive types.
  106. // Specialize for any types/templates that require special treatment
  107. template&lt;class T&gt;
  108. void save(T &amp; t);
  109. public:
  110. //////////////////////////////////////////////////////////
  111. // public interface used by programs that use the
  112. // serialization library
  113. // archives are expected to support this function
  114. void save_binary(void *address, std::size_t count);
  115. };
  116. </code></pre>
  117. Given a suitable definitions of <code style="white-space: normal">save</code>
  118. and <code style="white-space: normal">save_binary</code>,
  119. any program using serialization with a conforming C++ compiler should compile
  120. and run with this archive class.
  121. <h4>Optional Overrides</h4>
  122. The <code style="white-space: normal">detail::common_oarchive</code> class contains
  123. a number of functions that are used by various parts of the serialization library
  124. to help render the archive in a particular form.
  125. <dl>
  126. <dt><h4><code>void save_start(char const *)</code></h4></dt>
  127. <dd>
  128. <strong>Default</strong>:Does nothing.<br>
  129. <strong>Purpose</strong>:To inject/retrieve an object name into the archive. Used
  130. by XML archive to inject "&lt;name&gt;" before data.
  131. </dd>
  132. <p>
  133. <dt><h4><code>void save_end(char const *)</code></h4></dt>
  134. <dd>
  135. <strong>Default</strong>:Does nothing.<br>
  136. <strong>Purpose</strong>:To inject/retrieve an object name into the archive. Used
  137. by XML archive to inject "&lt;/name&gt;" after data.
  138. <dd>
  139. </dd>
  140. <p>
  141. <dt><h4><code>void end_preamble()</code></h4></dt>
  142. <dd>
  143. <strong>Default</strong>:Does nothing.<br>
  144. <strong>Purpose</strong>:Called <strong>each time</strong> user data is saved.
  145. It's not called when archive bookkeeping data is saved. This is used by XML archives
  146. to determine when to inject a "&gt;" character at the end of an XML header. XML output archives
  147. keep their own internal flag indicating that data being written is header data. This
  148. internal flag is reset when an object start tag is written. When
  149. <code style="white-space: normal">void end_preamble()</code> is invoked and this internal flag is set
  150. a "&gt;" character is appended to the output and the internal flag is reset. The default
  151. implementation for <code style="white-space: normal">void end_preamble()</code> is a no-op thereby permitting it
  152. to be optimised away for archive classes that don't use it.
  153. </dd>
  154. <p>
  155. <dt><h4><code>
  156. template&lt;class T&gt;
  157. void save_override(T & t, int);
  158. </code></h4></dt>
  159. <dd>
  160. <strong>Default</strong>:Invokes <code style="white-space: normal">archive::save(Archive & ar, t)</code><br>
  161. This is the main entry into the serialization library.<br>
  162. <strong>Purpose</strong>:This can be specialized in cases where the data is to be written
  163. to the archive in some special way. For example, XML archives implement special handling for
  164. name-value pairs by overriding this function template for name-value pairs.
  165. This replaces the default name-value pair handling, which is just to throw away the name,
  166. with one appropriate for XML which writes out the start of an XML tag with the correct object name.
  167. </dd>
  168. </dl>
  169. <h4>Types used by the serialization library</h4>
  170. The serialization library injects bookkeeping data into the serialization archive.
  171. This data includes things like object ids, version numbers, class names etc. Each
  172. of these objects is included in a wrapper so that the archive class can override the
  173. implementation of <code style="white-space: normal">void save_override(T & t, int);</code>.
  174. For example, in the XML archive, the override for this type renders an object_id equal to 23 as
  175. "object_id=_23". The following table lists the types defined in the
  176. <code style="white-space: normal">boost::archive namespace</code>
  177. used internally by the serialization library:
  178. <p>
  179. <table border>
  180. <tr><th align=left>type</th><th align=left><code style="white-space: normal">default<br>serialized as</code></th>
  181. <tr><td><code style="white-space: normal">version_type</code></td><td><code style="white-space: normal">unsigned int</code></td>
  182. <tr><td><code style="white-space: normal">object_id_type</code></td><td><code style="white-space: normal">unsigned int</code></td>
  183. <tr><td><code style="white-space: normal">object_id_reference_type</code></td><td><code style="white-space: normal">unsigned int</code></td>
  184. <tr><td><code style="white-space: normal">class_id_type</code></td><td><code style="white-space: normal">int</code></td>
  185. <tr><td><code style="white-space: normal">class_id_optional_type</code></td><td><code style="white-space: normal">nothing</code></td>
  186. <tr><td><code style="white-space: normal">class_id_reference_type</code></td><td><code style="white-space: normal">int</code></td>
  187. <tr><td><code style="white-space: normal">tracking_type</code></td><td><code style="white-space: normal">bool</code></td>
  188. <tr><td><code style="white-space: normal">classname_type</code></td><td><code style="white-space: normal">string</code></td>
  189. </table>
  190. <p>
  191. All of these are associated with a default serialization defined in terms of primitive types
  192. so it isn't a requirement to define <code style="white-space: normal">save_override</code>
  193. for these types.
  194. <p>
  195. These are defined in
  196. <a href="../../../boost/archive/basic_archive.hpp" target="basic_archive_hpp"><code style="white-space: normal">basic_archive.hpp</code></a>.
  197. All of these types have been assigned an
  198. <a target="detail" href="traits.html#level">implementation level</a> of
  199. <code style="white-space: normal">primitive</code> and are convertible to types such as int, unsigned int, etc.
  200. so that they have default implementations. This is illustrated by
  201. <a href="../../../boost/archive/basic_text_iarchive.hpp" target="basic_text_iarchive_hpp"><code style="white-space: normal">basic_text_iarchive.hpp</code></a>.
  202. which relies upon the default. However, in some cases, overrides will have to be
  203. explicitly provided for these types. For an example see
  204. <a href="../../../boost/archive/basic_xml_iarchive.hpp" target="basic_xml_iarchive_hpp"><code style="white-space: normal">basic_xml_iarchive.hpp</code></a>.
  205. <p>
  206. In real practice, we probably won't be quite done.
  207. One or more of the following issues may need to be addressed:
  208. <ul>
  209. <li>Even if we are using a conforming compiler, we might want our new archive class
  210. to be portable to non-conforming compilers.
  211. <li>Our archive format might require extra information inserted into it. For
  212. example, XML archives need &lt;name ... &gt;...&lt;/name&gt; surrounding
  213. all data objects.
  214. <li>Addressing any of the above may generate more issues to be addressed.
  215. <li>The archives included with the library are all templates which use a
  216. <code style="white-space: normal">stream</code> or
  217. <code style="white-space: normal">streambuf</code>
  218. as a template parameter rather than simple classes.
  219. Combined with the above, even more issues arise with non-conforming compilers.
  220. </ul>
  221. The attached <a target="class_diagram" href="class_diagram.html">class diagram</a>
  222. shows the relationships between classes used to implement the serialization library.
  223. <p>
  224. A close examination of the archives included with the library illustrate
  225. what it takes to make a portable archive that covers all data types.
  226. <h3><a name="usage">Usage</a></h3>
  227. The newly created archive will usually be stored in its own header module. All
  228. that is necessary is to include the header and construct an instance of the new archive.
  229. EXCEPT for one special case.
  230. <ul>
  231. <li>Instances of a derived class are serialized through a base class pointer.
  232. <li>Such instances are not "registered" neither implicitly nor explicitly. That
  233. is, the macro <code style="white-space: normal">BOOT_CLASS_EXPORT</code> is used
  234. to instantiate the serialization code for the included archives.
  235. </ul>
  236. To make this work, the following should be included after the archive
  237. class definition.
  238. <pre><code>
  239. BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive)
  240. </code></pre>
  241. Failure to do this will not inhibit the program from compiling, linking
  242. and executing properly - except in one case. If an instance of a derived
  243. class is serialized through a pointer to its base class, the program
  244. will throw an
  245. <a href="exceptions.html#unregistered_class"><code style="white-space: normal">unregistered_class</code></a>
  246. exception.
  247. <p>
  248. <h4><a name="testing">Testing</h4>
  249. Exhaustive testing of the library requires testing the different aspects of object
  250. serialization with each archive. There are 46 different tests that can run with any archive.
  251. There are 5 "standard archives" included with the system.
  252. (3 in systems that don't support wide charactor i/o).
  253. <p>
  254. In addition, there are 28 other tests which aren't related to any particular archive class.
  255. <p>
  256. The default <code style="white-space: normal">bjam</code> testing setup will run all
  257. the above described tests. This will result in as many as 46 archive tests * 5
  258. standard archives + 28 general tests = 258 tests. Note that a complete test of the
  259. library would include DLL vs static library, release vs debug so the actual total
  260. would be closer to 1032 tests.
  261. <p>
  262. For each archive there is a header file in the test directory similar to the one below.
  263. The name of this archive is passed to the test program by setting the
  264. environmental variable <code style="white-space: normal">BOOST_ARCHIVE_TEST</code>
  265. to the name of the header. Here is the header file
  266. <code style="white-space: normal">test_archive.hpp</code> . Test header files for
  267. other archives are similar.
  268. <pre><code>
  269. // text_archive test header
  270. // include output archive header
  271. #include &lt;boost/archive/text_oarchive.hpp&gt;
  272. // set name of test output archive
  273. typedef boost::archive::text_oarchive test_oarchive;
  274. // set name of test output stream
  275. typedef std::ofstream test_ostream;
  276. // repeat the above for input archive
  277. #include &lt;boost/archive/text_iarchive.hpp&gt;
  278. typedef boost::archive::text_iarchive test_iarchive;
  279. typedef std::ifstream test_istream;
  280. // define open mode for streams
  281. // binary archives should use std::ios_base::binary
  282. #define TEST_STREAM_FLAGS (std::ios_base::openmode)0
  283. </code></pre>
  284. To test a new archive, for example, portable binary archives, with the gcc compiler,
  285. make a header file <code style="white-space: normal">portable_binary_archive.hpp</code>
  286. and invoke <code style="white-space: normal">bjam</code> with
  287. <pre><code>
  288. -sBOOST_ARCHIVE_LIST=portable_binary_archive.hpp
  289. </code></pre>
  290. This process in encapsulated in the shell or cmd script
  291. <code style="white-space: normal">library_test</code> whose command line is
  292. <pre><code>
  293. library_test --toolset=gcc -sBOOST_ARCHIVE_LIST=portable_binary_archive.hpp
  294. </code></pre>
  295. <h3><a name="polymorphic">Polymorphic Archives</a></h3>
  296. <h4>Motivation</h4>
  297. All archives described so far are implemented as templates. Code to save and load
  298. data to archives is regenerated for each combination of archive class and data type.
  299. Under these cirumstances, a good optimizing compiler that can expand
  300. <code>inline</code> functions to enough depth will generate fast code.
  301. However:
  302. <ul>
  303. <li>Much inline code may be replicated.
  304. <li>If there are several archive classes, code will be regenerated for each archive class.
  305. <li>If serialization code is placed in a library, that library must be rebuilt
  306. each time a new archive class is created.
  307. <li>If serialization code is placed in a DLL,
  308. <ul>
  309. <li>The DLL will contain versions of code for each known archive type.
  310. This would result in loading of DLLs which contain
  311. much code that is not used - basically defeating one of the main motivations
  312. for choosing to use a DLL in the first place.
  313. <li>If a new archive is created and an application shipped, all DLLs have to be
  314. rebuilt, and reshipped along with the application which uses the new archive. Thus
  315. the other main motivation for using a DLL is defeated.
  316. </ul>
  317. </ul>
  318. <h4>Implementation</h4>
  319. The solution is the pair <code>polymorphic_oarchive</code>
  320. and <code>polymorphic_iarchive</code>. They present a common interface of virtual
  321. functions - no templates - that is equivalent to the standard templated one.
  322. This is shown in the accompanying
  323. <a target="class_diagram" href="class_diagram.html">class diagram</a>
  324. <p>
  325. The accompanying demo program in files
  326. <a target=demo_polymorphic_cp href="../example/demo_polymorphic.cpp"><code style="white-space: normal">demo_polymorphic.cpp</code></a>,
  327. <a target=demo_polymorphic_A_hpp href="../example/demo_polymorphic_A.hpp"><code style="white-space: normal">demo_polymorphic_A.hpp</code></a>, and
  328. <a target=demo_polymorphic_A_cpp href="../example/demo_polymorphic_A.cpp"><code style="white-space: normal">demo_polymorphic_A</code></a>
  329. show how polymorphic archives are to be used. Note the following:
  330. <ul>
  331. <li><a target=demo_polymorphic_A_hpp href="../example/demo_polymorphic_A.hpp"><code style="white-space: normal">demo_polymorphic_A.hpp</code></a> and
  332. <a target=demo_polymorphic_A_cpp href="../example/demo_polymorphic_A.cpp"><code style="white-space: normal">demo_polymorphic_A.cpp</code></a>
  333. contain no templates and no reference to any specific archive implementation. That is, they will
  334. only have to be compiled once for all archive implementations. This even applies to archives classes
  335. created in the future.
  336. <li>The main program <a target=demo_polymorphic_cp href="../example/demo_polymorphic.cpp"><code style="white-space: normal">demo_polymorphic.cpp</code></a>
  337. specifies a specific archive implementation.
  338. </ul>
  339. As can be seen in the
  340. <a target="class_diagram" href="class_diagram.html">class diagram</a>
  341. and the header files, this implementation is just a composition of the polymorphic
  342. interface and the standard template driven implementation. This composition is
  343. accomplished by the templates
  344. <a target=polymorphic_iarchive_route_hpp href="../../../boost/archive/detail/polymorphic_iarchive_route.hpp"><code style="white-space: normal">polymorphic_iarchive_route.hpp</code></a>
  345. and
  346. <a target=polymorphic_oarchive_route_hpp href="../../../boost/archive/detail/polymorphic_oarchive_route.hpp"><code style="white-space: normal">polymorphic_oarchive_route.hpp</code></a>
  347. which redirect calls to the polymorphic archives to the specific archive.
  348. As these contain no code specific to the particular implementation archive, they can be used to create
  349. a polymorphic archive implementation from any functioning templated archive implementation.
  350. <p>
  351. As a convenience, small header files have been included which contain
  352. a <code style="white-space: normal">typedef</code> for a polymorphic implementation for each corresponding
  353. templated one. For example, the headers
  354. <a target=polymorphic_text_iarchive_hpp href="../../../boost/archive/polymorphic_text_iarchive.hpp"><code style="white-space: normal">polymorphic_text_iarchive.hpp</code></a>
  355. and
  356. <a target=polymorphic_text_oarchive_hpp href="../../../boost/archive/polymorphic_text_oarchive.hpp"><code style="white-space: normal">polymorphic_text_oarchive.hpp</code></a>.
  357. contain the <code style="white-space: normal">typedef</code> for the polymorphic implementation
  358. of the standard text archive classes
  359. <a target=text_iarchive_hpp href="../../../boost/archive/text_iarchive.hpp"><code style="white-space: normal">text_iarchive.hpp</code></a>
  360. and
  361. <a target=text_oarchive_hpp href="../../../boost/archive/text_oarchive.hpp"><code style="white-space: normal">text_oarchive.hpp</code></a>
  362. respectively. All included polymorphic archives use the same naming scheme.
  363. <h4>Usage</h4>
  364. Polymorphic archives address the issues raised above regarding templated implementation.
  365. That is, there is no replicated code, and no recompilation for new archives. This will
  366. result in smaller executables for program which use more than one type of archive, and
  367. smaller DLLS. There is a penalty for calling archive functions through a virtual function
  368. dispatch table and there is no possibility for a compiler to <code style="white-space: normal">inline</code>
  369. archive functions. This will result in a detectable degradation in performance for
  370. saving and loading archives.
  371. <p>
  372. Note that the concept of polymophic archives is fundamentally incompatible with the
  373. serialization of new types that are marked "primitive" by the user with:
  374. <pre><code>
  375. BOOST_CLASS_IMPLEMENTATION(my_primitive_type, boost::serialization::primitive_type)
  376. </code></pre>
  377. Code to implement serialization for these types is instantiated "on the fly" in the user's program.
  378. But this conflicts with the whole purpose of the polymorphic archive. An attempt to
  379. serialize such a primitive type will result in a compilation error since the common polymorhic
  380. interface is static and cannot instantiate code for a new type.
  381. <p>
  382. The main utility of polymorphic archives will be to permit the building of class DLLs that will
  383. include serialization code for all present and future archives with no redundant code.
  384. <hr>
  385. <p><i>&copy; Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004.
  386. Distributed under the Boost Software License, Version 1.0. (See
  387. accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  388. </i></p>
  389. </body>
  390. </html>