special.html 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  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-4 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; charset=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 - Special Considerations</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">Special Considerations</h2>
  24. </td>
  25. </tr>
  26. </table>
  27. <hr>
  28. <dl class="page-index">
  29. <dt><a href="#objecttracking">Object Tracking</a>
  30. <dt><a href="#classinfo">Class Information</a>
  31. <dt><a href="#helpersupport">Helper Support</a>
  32. <dt><a href="#portability">Archive Portability</a>
  33. <dl class="page-index">
  34. <dt><a href="#numerics">Numerics</a>
  35. <dt><a href="#traits">Traits</a>
  36. </dl>
  37. <dt><a href="#binary_archives">Binary Archives</a>
  38. <dt><a href="#xml_archives">XML Archives</a>
  39. <dt><a href="#export">Exporting Class Serialization</a>
  40. <dt><a href="#static_libraries">Static Libraries and Serialization</a>
  41. <dt><a href="#dlls">DLLS - Serialization and Runtime Linking</a>
  42. <dt><a href="#plugins">Plugins</a>
  43. <dt><a href="#multi_threading">Multi-Threading</a>
  44. <dt><a href="#optimizations">Optimizations</a>
  45. <dt><a href="exceptions.html">Archive Exceptions</a>
  46. <dt><a href="exception_safety.html">Exception Safety</a>
  47. </dl>
  48. <h3><a name="objecttracking">Object Tracking</a></h3>
  49. Depending on how the class is used and other factors, serialized objects
  50. may be tracked by memory address. This prevents the same object from being
  51. written to or read from an archive multiple times. These stored addresses
  52. can also be used to delete objects created during a loading process
  53. that has been interrupted by throwing of an exception.
  54. <p>
  55. This could cause problems in
  56. progams where the copies of different objects are saved from the same address.
  57. <pre><code>
  58. template&lt;class Archive&gt;
  59. void save(boost::basic_oarchive &amp; ar, const unsigned int version) const
  60. {
  61. for(int i = 0; i &lt; 10; ++i){
  62. A x = a[i];
  63. ar &lt;&lt; x;
  64. }
  65. }
  66. </code></pre>
  67. In this case, the data to be saved exists on the stack. Each iteration
  68. of the loop updates the value on the stack. So although the data changes
  69. each iteration, the address of the data doesn't. If a[i] is an array of
  70. objects being tracked by memory address, the library will skip storing
  71. objects after the first as it will be assumed that objects at the same address
  72. are really the same object.
  73. <p>
  74. To help detect such cases, output archive operators expect to be passed
  75. <code style="white-space: normal">const</code> reference arguments.
  76. <p>
  77. Given this, the above code will invoke a compile time assertion.
  78. The obvious fix in this example is to use
  79. <pre><code>
  80. template&lt;class Archive&gt;
  81. void save(boost::basic_oarchive &amp; ar, const unsigned int version) const
  82. {
  83. for(int i = 0; i &lt; 10; ++i){
  84. ar &lt;&lt; a[i];
  85. }
  86. }
  87. </code></pre>
  88. which will compile and run without problem.
  89. The usage of <code style="white-space: normal">const</code> by the output archive operators
  90. will ensure that the process of serialization doesn't
  91. change the state of the objects being serialized. An attempt to do this
  92. would constitute augmentation of the concept of saving of state with
  93. some sort of non-obvious side effect. This would almost surely be a mistake
  94. and a likely source of very subtle bugs.
  95. <p>
  96. Unfortunately, implementation issues currently prevent the detection of this kind of
  97. error when the data item is wrapped as a name-value pair.
  98. <p>
  99. A similar problem can occur when different objects are loaded to an address
  100. which is different from the final location:
  101. <pre><code>
  102. template&lt;class Archive&gt;
  103. void load(boost::basic_oarchive &amp; ar, const unsigned int version) const
  104. {
  105. for(int i = 0; i &lt; 10; ++i){
  106. A x;
  107. ar &gt;&gt; x;
  108. std::m_set.insert(x);
  109. }
  110. }
  111. </code></pre>
  112. In this case, the address of <code>x</code> is the one that is tracked rather than
  113. the address of the new item added to the set. Left unaddressed
  114. this will break the features that depend on tracking such as loading an object through a pointer.
  115. Subtle bugs will be introduced into the program. This can be
  116. addressed by altering the above code thusly:
  117. <pre><code>
  118. template&lt;class Archive&gt;
  119. void load(boost::basic_iarchive &amp; ar, const unsigned int version) const
  120. {
  121. for(int i = 0; i &lt; 10; ++i){
  122. A x;
  123. ar &gt;&gt; x;
  124. std::pair&lt;std::set::const_iterator, bool&gt; result;
  125. result = std::m_set.insert(x);
  126. ar.reset_object_address(& (*result.first), &x);
  127. }
  128. }
  129. </code></pre>
  130. This will adjust the tracking information to reflect the final resting place of
  131. the moved variable and thereby rectify the above problem.
  132. <p>
  133. If it is known a priori that no pointer
  134. values are duplicated, overhead associated with object tracking can
  135. be eliminated by setting the object tracking class serialization trait
  136. appropriately.
  137. <p>
  138. By default, data types designated primitive by the
  139. <a target="detail" href="traits.html#level">Implementation Level</a>
  140. class serialization trait are never tracked. If it is desired to
  141. track a shared primitive object through a pointer (e.g. a
  142. <code style="white-space: normal">long</code> used as a reference count), It should be wrapped
  143. in a class/struct so that it is an identifiable type.
  144. The alternative of changing the implementation level of a <code style="white-space: normal">long</code>
  145. would affect all <code style="white-space: normal">long</code>s serialized in the whole
  146. program - probably not what one would intend.
  147. <p>
  148. It is possible that we may want to track addresses even though
  149. the object is never serialized through a pointer. For example,
  150. a virtual base class need be saved/loaded only once. By setting
  151. this serialization trait to <code style="white-space: normal">track_always</code>, we can suppress
  152. redundant save/load operations.
  153. <pre><code>
  154. BOOST_CLASS_TRACKING(my_virtual_base_class, boost::serialization::track_always)
  155. </code></pre>
  156. <h3><a name="helpersupport">Helper Support</a></h3>
  157. Some types, specially those with complicated lifetime behavior or limited
  158. access to their internal state, might need or benefit from elaborate serialization
  159. algorithms. The prinicple motivating case is that of shared_ptr. As instances
  160. are loaded, they have to be "matched up" with any other instances which have
  161. already been loaded. Thus, a table of previously loaded instances has to be
  162. maintained while the archive containing the shared_ptr instances is being loaded.
  163. Without maintaining such a table, the shared_ptr would be a serializable type.
  164. <p>
  165. To implement this facility, one declares a <i>helper object</i>
  166. associated to the current archive that can be used to store contextual
  167. information relevant to the particular type serialization algorithm.
  168. <pre><code>
  169. template<class T>
  170. class shared_ptr
  171. {
  172. ...
  173. };
  174. BOOST_SERIALIZATION_SPLIT_FREE(shared_ptr)
  175. class shared_ptr_serialization_helper
  176. {
  177. // table of previously loaded shared_ptr
  178. // lookup a shared_ptr from the object address
  179. shared_ptr<T> lookup(const T *);
  180. // insert a new shared_ptr
  181. void insert<shared_ptr<T> >(const shared_ptr<T> *);
  182. };
  183. namespace boost {
  184. namespace serialization {
  185. template&lt;class Archive&gt;
  186. void save(Archive &amp; ar, const shared_ptr &amp; x, const unsigned int /* version */)
  187. {
  188. // save shared ptr
  189. ...
  190. }
  191. template&lt;class Archive&gt;
  192. void load(Archive &amp; ar, shared_ptr &amp; x, const unsigned int /* version */)
  193. {
  194. // get a unique identifier. Using a constant means that all shared pointers
  195. // are held in the same set. Thus we detect handle multiple pointers to the
  196. // same value instances in the archive.
  197. const void * shared_ptr_helper_id = 0;
  198. shared_ptr_serialization_helper &amp; hlp =
  199. ar.template get_helper&lt;shared_ptr_serialization_helper&gt;(helper_instance_id);
  200. // load shared pointer object
  201. ...
  202. shared_ptr_serialization_helper &amp; hlp =
  203. ar.template get_helper&lt;shared_ptr_serialization_helper&gt;(shared_ptr_helper_id);
  204. // look up object in helper object
  205. T * shared_object hlp.lookup(...);
  206. // if found, return the one from the table
  207. // load the shared_ptr data
  208. shared_ptr<T> sp = ...
  209. // and add it to the table
  210. hlp.insert(sp);
  211. // implement shared_ptr_serialization_helper load algorithm with the aid of hlp
  212. }
  213. } // namespace serialization
  214. } // namespace boost
  215. </code></pre>
  216. <code style="white-space: normal">get_helper&lt;shared_ptr_serialization_helper&gt;();</code>
  217. creates a helper object associated to the archive the first time it is invoked;
  218. subsequent invocations return a reference to the object created in the first
  219. place, so that <code style="white-space: normal">hlp</code> can effectively be
  220. used to store contextual information persisting through the serialization
  221. of different <code style="white-space: normal">complex_type</code> objects on
  222. the same archive.
  223. <p>
  224. Helpers may be created for saving and loading archives.
  225. The same program might have several different helpers or the same helper instantiated
  226. separately from different parts of the program. This is what makes the helper_instance_id
  227. necessary. In principle it could be any unique integer. In practice it seems
  228. easiest to use the address of the serialization function which contains it. The
  229. above example uses this technique.
  230. <h3><a name="classinfo">Class Information</a></h3>
  231. By default, for each class serialized, class information is written to the archive.
  232. This information includes version number, implementation level and tracking
  233. behavior. This is necessary so that the archive can be correctly
  234. deserialized even if a subsequent version of the program changes
  235. some of the current trait values for a class. The space overhead for
  236. this data is minimal. There is a little bit of runtime overhead
  237. since each class has to be checked to see if it has already had its
  238. class information included in the archive. In some cases, even this
  239. might be considered too much. This extra overhead can be eliminated
  240. by setting the
  241. <a target="detail" href="traits.html#level">implementation level</a>
  242. class trait to: <code style="white-space: normal">boost::serialization::object_serializable</code>.
  243. <p>
  244. <i>Turning off tracking and class information serialization will result
  245. in pure template inline code that in principle could be optimised down
  246. to a simple stream write/read.</i> Elimination of all serialization overhead
  247. in this manner comes at a cost. Once archives are released to users, the
  248. class serialization traits cannot be changed without invalidating the old
  249. archives. Including the class information in the archive assures us
  250. that they will be readable in the future even if the class definition
  251. is revised. A light weight structure such as a display pixel might be
  252. declared in a header like this:
  253. <pre><code>
  254. #include &lt;boost/serialization/serialization.hpp&gt;
  255. #include &lt;boost/serialization/level.hpp&gt;
  256. #include &lt;boost/serialization/tracking.hpp&gt;
  257. // a pixel is a light weight struct which is used in great numbers.
  258. struct pixel
  259. {
  260. unsigned char red, green, blue;
  261. template&lt;class Archive&gt;
  262. void serialize(Archive &amp; ar, const unsigned int /* version */){
  263. ar &lt;&lt; red &lt;&lt; green &lt;&lt; blue;
  264. }
  265. };
  266. // elminate serialization overhead at the cost of
  267. // never being able to increase the version.
  268. BOOST_CLASS_IMPLEMENTATION(pixel, boost::serialization::object_serializable);
  269. // eliminate object tracking (even if serialized through a pointer)
  270. // at the risk of a programming error creating duplicate objects.
  271. BOOST_CLASS_TRACKING(pixel, boost::serialization::track_never)
  272. </code></pre>
  273. <h3><a name="portability">Archive Portability</a></h3>
  274. Several archive classes create their data in the form of text or a portable binary format.
  275. It should be possible to save such a class on one platform and load it on another.
  276. This is subject to a couple of conditions.
  277. <h4><a name="numerics">Numerics</a></h4>
  278. The architecture of the machine reading the archive must be able hold the data
  279. saved. For example, the gcc compiler reserves 4 bytes to store a variable of type
  280. <code style="white-space: normal">wchar_t</code> while other compilers reserve only 2 bytes.
  281. So it's possible that a value could be written that couldn't be represented by the loading program. This is a
  282. fairly obvious situation and easily handled by using the numeric types in
  283. <a target="cstding" href="../../../boost/cstdint.hpp">&lt;boost/cstdint.hpp&gt;</a>
  284. <P>
  285. A special integral type is <code>std::size_t</code> which is a typedef
  286. of an integral types guaranteed to be large enough
  287. to hold the size of any collection, but its actual size can differ depending
  288. on the platform. The
  289. <a href="wrappers.html#collection_size_type"><code>collection_size_type</code></a>
  290. wrapper exists to enable a portable serialization of collection sizes by an archive.
  291. Recommended choices for a portable serialization of collection sizes are to
  292. use either 64-bit or variable length integer representation.
  293. <h4><a name="traits">Traits</a></h4>
  294. Another potential problem is illustrated by the following example:
  295. <pre><code>
  296. template&lt;class T&gt;
  297. struct my_wrapper {
  298. template&lt;class Archive&gt;
  299. Archive & serialize ...
  300. };
  301. ...
  302. class my_class {
  303. wchar_t a;
  304. short unsigned b;
  305. template&lt;class Archive&gt;
  306. Archive & serialize(Archive & ar, unsigned int version){
  307. ar & my_wrapper(a);
  308. ar & my_wrapper(b);
  309. }
  310. };
  311. </code></pre>
  312. If <code style="white-space: normal">my_wrapper</code> uses default serialization
  313. traits there could be a problem. With the default traits, each time a new type is
  314. added to the archive, bookkeeping information is added. So in this example, the
  315. archive would include such bookkeeping information for
  316. <code style="white-space: normal">my_wrapper&lt;wchar_t&gt;</code> and for
  317. <code style="white-space: normal">my_wrapper&lt;short_unsigned&gt;</code>.
  318. Or would it? What about compilers that treat
  319. <code style="white-space: normal">wchar_t</code> as a
  320. synonym for <code style="white-space: normal">unsigned short</code>?
  321. In this case there is only one distinct type - not two. If archives are passed between
  322. programs with compilers that differ in their treatment
  323. of <code style="white-space: normal">wchar_t</code> the load operation will fail
  324. in a catastrophic way.
  325. <p>
  326. One remedy for this is to assign serialization traits to the template
  327. <code style="white-space: normal">my_template</code> such that class
  328. information for instantiations of this template is never serialized. This
  329. process is described <a target="detail" href="traits.html#templates">above</a> and
  330. has been used for <a target="detail" href="wrappers.html#nvp"><strong>Name-Value Pairs</strong></a>.
  331. Wrappers would typically be assigned such traits.
  332. <p>
  333. Another way to avoid this problem is to assign serialization traits
  334. to all specializations of the template <code style="white-space: normal">my_wrapper</code>
  335. for all primitive types so that class information is never saved. This is what has
  336. been done for our implementation of serializations for STL collections.
  337. <h3><a name="binary_archives">Binary Archives</a></h3>
  338. Standard stream i/o on some systems will expand linefeed characters to carriage-return/linefeed
  339. on output. This creates a problem for binary archives. The easiest way to handle this is to
  340. open streams for binary archives in "binary mode" by using the flag
  341. <code style="white-space: normal">ios::binary</code>. If this is not done, the archive generated
  342. will be unreadable.
  343. <p>
  344. Unfortunately, no way has been found to detect this error before loading the archive. Debug builds
  345. will assert when this is detected so that may be helpful in catching this error.
  346. <h3><a name="xml_archives">XML Archives</a></h3>
  347. XML archives present a somewhat special case.
  348. XML format has a nested structure that maps well to the "recursive class member visitor" pattern
  349. used by the serialization system. However, XML differs from other formats in that it
  350. requires a name for each data member. Our goal is to add this information to the
  351. class serialization specification while still permiting the the serialization code to be
  352. used with any archive. This is achived by requiring that all data serialized to an XML archive
  353. be serialized as a <a target="detail" href="wrappers.html#nvp">name-value pair</a>.
  354. The first member is the name to be used as the XML tag for the
  355. data item while the second is a reference to the data item itself. Any attempt to serialize data
  356. not wrapped in a in a <a target="detail" href="wrappers.html#nvp">name-value pair</a> will
  357. be trapped at compile time. The system is implemented in such a way that for other archive classes,
  358. just the value portion of the data is serialized. The name portion is discarded during compilation.
  359. So by always using <a target="detail" href="wrappers.html#nvp">name-value pairs</a>, it will
  360. be guaranteed that all data can be serialized to all archive classes with maximum efficiency.
  361. <h3><a name="export">Exporting Class Serialization</a></h3>
  362. <a target="detail" href="traits.html#export">Elsewhere</a> in this manual, we have described
  363. <code style="white-space: normal">BOOST_CLASS_EXPORT</code>.
  364. Export implies two things:
  365. <ul>
  366. <li>Instantiates code which is not otherwise referred to.
  367. <li>Associates an external identifier with the class to be serialized.
  368. The fact that the class isn't explicitly referred to implies this
  369. requirement.
  370. </ul>
  371. In C++, usage of code not explicitly referred to is implemented via
  372. virtual functions. Hence, the need for export is implied by the
  373. usage of a derived class that is manipulated via a pointer or
  374. reference to its base class.
  375. <p>
  376. <code style="white-space: normal">BOOST_CLASS_EXPORT</code> in the same
  377. source module that includes any of the archive class headers will
  378. instantiate code required to serialize polymorphic pointers of
  379. the indicated type to the all those archive classes. If no
  380. archive class headers are included, then no code will be instantiated.
  381. <p>
  382. Note that the implemenation of this functionality requires
  383. that the <code style="white-space: normal">BOOST_CLASS_EXPORT</code>
  384. macro appear <b>after</b> the inclusion of any archive
  385. class headers for which code is to be instantiated.
  386. So, code that uses <code style="white-space: normal">BOOST_CLASS_EXPORT</code>
  387. will look like the following:
  388. <pre><code>
  389. #include &lt;boost/archive/text_oarchive.hpp&gt;
  390. #include &lt;boost/archive/text_oarchive.hpp&gt;
  391. ... // other archives
  392. #include "a.hpp" // header declaration for class a
  393. BOOST_CLASS_EXPORT(a)
  394. ... // other class headers and exports
  395. </code></pre>
  396. This will be true regardless of whether the code is part
  397. of a stand alone executable, a static library or
  398. a dyanmic or shared library.
  399. <p>
  400. Including
  401. <code style="white-space: normal">BOOST_CLASS_EXPORT</code>
  402. in the "a.hpp" header itself as one would do with
  403. other serialization traits will make it difficult
  404. or impossible to follow the rule above regarding
  405. inclusion of archive headers before
  406. <code style="white-space: normal">BOOST_CLASS_EXPORT</code>
  407. is invoked. This can best be addressed by using
  408. <code style="white-space: normal">BOOST_CLASS_EXPORT_KEY</code>
  409. in the header declarations and
  410. <code style="white-space: normal">BOOST_CLASS_EXPORT_IMPLEMENT</code>
  411. in the class definition file.
  412. <p>
  413. This system has certain implications for placing code in static or shared
  414. libraries. Placing <code style="white-space: normal">BOOST_CLASS_EXPORT</code>
  415. in library code will have no effect unless archive class headers are
  416. also included. So when building a library, one should include all headers
  417. for all the archive classes which he anticipates using. Alternatively,
  418. one can include headers for just the
  419. <a href="archive_reference.html#polymorphic">Polymoprhic Archives</a>.
  420. <p>
  421. Strictly speaking, export should not be necessary if all pointer serialization
  422. occurs through the most derived class. However, in order to detect
  423. what would be a catastophic error, the library traps ALL serializations through
  424. a pointer to a polymorphic class which are not exported or otherwise registered.
  425. So, in practice, be prepared to register or export all classes with one
  426. or more virtual functions which are serialized through a pointer.
  427. <p>
  428. Note that the implementation of this functionality depends upon vendor
  429. specific extensions to the C++ language. So, there is no guaranteed portability
  430. of programs which use this facility. However, all C++ compilers which
  431. are tested with boost provide the required extensions. The library
  432. includes the extra declarations required by each of these compilers.
  433. It's reasonable to expect that future C++ compilers will support
  434. these extensions or something equivalent.
  435. <h3><a name="static_libraries">Static Libraries and Serialization</a></h3>
  436. Code for serialization of data types can be saved in libraries
  437. just as it can for the rest of the type implementation.
  438. This works well, and can save a huge amount of compilation time.
  439. <ul>
  440. <li>Only compile serialization definitions in the library.
  441. <li>Explicitly instantiate serialization code for ALL
  442. archive classes you intend to use in the library.
  443. <li>For exported types, only use <code style="white-space: normal">BOOST_CLASS_EXPORT_KEY</code>
  444. in headers.
  445. <li>For exported types, only use <code style="white-space: normal">BOOST_CLASS_EXPORT_IMPLEMENT</code>
  446. in definitions compiled in the library. For any particular type,
  447. there should be only one file which contains
  448. <code style="white-space: normal">BOOST_CLASS_EXPORT_IMPLEMENT</code>
  449. for that type. This ensures that only one copy
  450. of serialization code will exist within the program. It avoids
  451. wasted space and the possibility of having different
  452. versions of the serialization code in the same program.
  453. Including
  454. <code style="white-space: normal">BOOST_CLASS_EXPORT_IMPLEMENT</code>
  455. in multiple files could result in a failure
  456. to link due to duplicated symbols or the throwing
  457. of a runtime exception.
  458. <li> Code for serialization should be only in the library,
  459. <li>Familiarize yourself with the <b>PIMPL</b> idiom.
  460. </ul>
  461. This is illustrated by
  462. <a href = "../example/demo_pimpl.cpp" target="demo_pimpl">
  463. <code style="white-space: normal">demo_pimpl.cpp</code>
  464. </a>,
  465. <a href = "../example/demo_pimpl_A.cpp" target="demo_pimpl">
  466. <code style="white-space: normal">demo_pimpl_A.cpp</code>
  467. </a>
  468. and
  469. <a href = "../example/demo_pimpl_A.hpp" target="demo_pimpl">
  470. <code style="white-space: normal">demo_pimpl_A.hpp</code>
  471. </a>
  472. where implementation of serializaton is in a static library
  473. completely separate from the main program.
  474. <h3><a name="dlls">DLLS - Serialization and Runtime Linking</a></h3>
  475. Serialization code can be placed in libraries to be linked at runtime. That is,
  476. code can be placed in DLLS(Windows) Shared Libraries(*nix), or static libraries
  477. as well as the main executable. The best technique is the
  478. same as that described above for libraries. The serialization
  479. library test suite includes the following programs
  480. to illustrate how this works:
  481. <p>
  482. <a href = "../test/test_dll_simple.cpp" target="test_dll_simple">
  483. <code style="white-space: normal">test_dll_simple</code>
  484. </a>,
  485. and
  486. <a href = "../test/dll_a.cpp" target="dll_a">
  487. <code style="white-space: normal">dll_a.cpp</code>
  488. </a>
  489. where implementation of serializaton is also completely separate
  490. from the main program but the code is loaded at runtime. In this
  491. example, this code is loaded automatically when the program which
  492. uses it starts up, but it could just as well be loaded and unloaded
  493. with an OS dependent API call.
  494. <p>
  495. Also included are
  496. <a href = "../test/test_dll_exported.cpp" target="test_dll_exported">
  497. <code style="white-space: normal">test_dll_exported.cpp</code>
  498. </a>,
  499. and
  500. <a href = "../test/polymorphic_derived2.cpp" target="polymorphic_derived2">
  501. <code style="white-space: normal">polymorphic_derived2.cpp</code>
  502. </a>
  503. which are similar to the above but include tests of the export
  504. and no_rtti facilities in the context of DLLS.
  505. <p>
  506. For best results, write your code to conform to the following
  507. guidelines:
  508. <ul>
  509. <li>Don't include <code>inline</code> code in classes used in DLLS.
  510. This will generate duplicate code in the DLLS and mainline. This
  511. needlessly duplicates code. Worse, it makes is possible for
  512. different versions of the same code to exist simultaneously. This
  513. type of error turns out to be excruciatingly difficult to debug.
  514. Finally, it opens the possibility that a module being referred to
  515. might be explictly unloaded which would (hopefully) result in
  516. a runtime error. This is another bug that is not always
  517. reproducible or easy to find. For class member templates use something like
  518. <pre><code>
  519. template&lt;class Archive&gt;
  520. void serialize(Archive & ar, const unsigned int version);
  521. </code></pre>
  522. in the header, and
  523. <pre><code>
  524. template&lt;class Archive&gt;
  525. void myclass::serialize(Archive & ar, const unsigned int version){
  526. ...
  527. }
  528. BOOST_CLASS_EXPORT_IMPLEMENT(my_class)
  529. #include &lt;boost/archive/text_oarchive&gt;
  530. #include &lt;boost/archive/text_iarchive&gt;
  531. template myclass::serialize(boost::archive::text_oarchive & ar, const unsigned int version);
  532. template myclass::serialize(boost::archive::text_iarchive & ar, const unsigned int version);
  533. ... // repeat for each archive class to be used.
  534. </code></pre>
  535. in the implementation file. This will result in generation of all code
  536. required in only one place. The library does not detect this type of error for you.
  537. <li>If DLLS are to be loaded and unloaded explicitly (e.g. using <code>dlopen</code> in *nix or
  538. <code>LoadLibrary</code> in Windows). Try to arrange that they are unloaded in the reverse
  539. sequence. This should guarantee that problems are avoided even if the
  540. above guideline hasn't been followed.
  541. </ul>
  542. <h3><a name="plugins">Plugins</a></h3>
  543. In order to implement the library, various facilities for runtime
  544. manipulation of types at runtime were required. These
  545. are <a target="detail" href="extended_type_info.html"><code>extended_type_info</code></a>
  546. for associating classes with external identifying strings (<b>GUID</b>)
  547. and <a target="detail" href="void_cast.html"><code>void_cast</code></a>
  548. for casting between pointers of related types.
  549. To complete the functionality of
  550. <a target="detail" href="extended_type_info.html"><code>extended_type_info</code></a>
  551. the ability to construct and destroy corresponding types has been
  552. added. In order to use this functionality, one must specify
  553. how each type is created. This should be done at the time
  554. a class is exported. So, a more complete example of the code above would be:
  555. <pre><code>
  556. #include &lt;boost/archive/text_oarchive.hpp&gt;
  557. #include &lt;boost/archive/text_oarchive.hpp&gt;
  558. ... // other archives
  559. #include "a.hpp" // header declaration for class a
  560. // this class has a default constructor
  561. BOOST_SERIALIZATION_FACTORY_0(a)
  562. // as well as one that takes one integer argument
  563. BOOST_SERIALIZATION_FACTORY_1(a, int)
  564. // specify the GUID for this class
  565. BOOST_CLASS_EXPORT(a)
  566. ... // other class headers and exports
  567. </code></pre>
  568. With this in place, one can construct, serialize and destroy a class
  569. about which is known only the <b>GUID</b> and a base class.
  570. <h3><a name="multi_threading">Multi-Threading</a></h3>
  571. The fundamental purpose of serialization would conflict with multiple
  572. threads concurrently writing/reading from/to a single open archive instance.
  573. The library implementation presumes that the application avoids such a situtation.
  574. <p>
  575. However, Writing/Reading different archives simultaneously
  576. in different tasks is permitted as each archive instance is (almost)
  577. completely independent from any other archive instance. The only shared
  578. information is some type tables which have been implemented using a
  579. lock-free thread-safe
  580. <a target="detail" href="singleton.html">
  581. <code style="white-space: normal">singleton</code>
  582. </a>
  583. described elsewhere in this documentation.
  584. <p>
  585. This singleton implementation guarantees that all of this shared
  586. information is initialized when the code module which contains
  587. it is loaded. The serialization library takes care to
  588. ensure that these data structures are not subsequently
  589. modified. The only time there could be a problem would
  590. be if code is loaded/unloaded while another task is
  591. serializing data. This could only occur for types whose
  592. serialization is implemented in a dynamically loaded/unloaded DLL
  593. or shared library. So if the following is avoided:
  594. <ul>
  595. <li>Accessing the same archive instance from different tasks.
  596. <li>Loading/Unloading DLLS or shared libraries while any archive
  597. instances are open.
  598. </ul>
  599. The library should be thread safe.
  600. <h3><a name="optimizations">Optimizations</a></h3>
  601. In performance critical applications that serialize large sets of contiguous data of homogeneous
  602. types one wants to avoid the overhead of serializing each element individually, which is
  603. the motivation for the <a href="wrappers.html#arrays"><code>array</code></a>
  604. wrapper.
  605. Serialization functions for data types containing contiguous arrays of homogeneous
  606. types, such as for <code>std::vector</code>, <code>std::valarray</code> or
  607. <code>boost::multiarray</code> should serialize them using an
  608. <a href="wrappers.html#arrays"><code>array</code></a> wrapper to make use of
  609. these optimizations.
  610. Archive types that can provide optimized serialization for contiguous arrays of
  611. homogeneous types should implement these by overloading the serialization of
  612. the <a href="wrappers.html#arrays"><code>array</code></a> wrapper, as is done
  613. for the binary archives.
  614. <h3><a href="exceptions.html">Archive Exceptions</a></h3>
  615. <h3><a href="exception_safety.html">Exception Safety</a></h3>
  616. <hr>
  617. <p><i>&copy; Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004.
  618. Distributed under the Boost Software License, Version 1.0. (See
  619. accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  620. </i></p>
  621. </body>
  622. </html>