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