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 . 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<class Archive> 60void save(boost::basic_oarchive & ar, const unsigned int version) const 61{ 62 for(int i = 0; i < 10; ++i){ 63 A x = a[i]; 64 ar << 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<class Archive> 82void save(boost::basic_oarchive & ar, const unsigned int version) const 83{ 84 for(int i = 0; i < 10; ++i){ 85 ar << 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<class Archive> 104void load(boost::basic_oarchive & ar, const unsigned int version) const 105{ 106 for(int i = 0; i < 10; ++i){ 107 A x; 108 ar >> 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<class Archive> 121void load(boost::basic_iarchive & ar, const unsigned int version) const 122{ 123 for(int i = 0; i < 10; ++i){ 124 A x; 125 ar >> x; 126 std::pair<std::set::const_iterator, bool> 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<class Archive> 194void save(Archive & ar, const shared_ptr & x, const unsigned int /* version */) 195{ 196 // save shared ptr 197 ... 198} 199 200template<class Archive> 201void load(Archive & ar, shared_ptr & 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 & hlp = 209 ar.template get_helper<shared_ptr_serialization_helper>(helper_instance_id); 210 211 // load shared pointer object 212 ... 213 214 shared_ptr_serialization_helper & hlp = 215 ar.template get_helper<shared_ptr_serialization_helper>(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<shared_ptr_serialization_helper>();</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 <boost/serialization/serialization.hpp> 275#include <boost/serialization/level.hpp> 276#include <boost/serialization/tracking.hpp> 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<class Archive> 283 void serialize(Archive & ar, const unsigned int /* version */){ 284 ar << red << green << 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"><boost/cstdint.hpp></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<class T> 323struct my_wrapper { 324 template<class Archive> 325 Archive & serialize ... 326}; 327 328... 329 330class my_class { 331 wchar_t a; 332 short unsigned b; 333 template<class Archive> 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<wchar_t></code> and for 345<code style="white-space: normal">my_wrapper<short_unsigned></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 <boost/archive/text_oarchive.hpp> 423#include <boost/archive/text_oarchive.hpp> 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<class Archive> 561void serialize(Archive & ar, const unsigned int version); 562</code></pre> 563in the header, and 564 565<pre><code> 566template<class Archive> 567void myclass::serialize(Archive & ar, const unsigned int version){ 568 ... 569} 570 571BOOST_CLASS_EXPORT_IMPLEMENT(my_class) 572 573#include <boost/archive/text_oarchive> 574#include <boost/archive/text_iarchive> 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 <boost/archive/text_oarchive.hpp> 605#include <boost/archive/text_oarchive.hpp> 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>© 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> 683