Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/serialization/doc/shared_ptr.html @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 8.8 KB
Line 
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>Template serialization - shared_ptr</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">Template serialization - <code style="white-space: normal">shared_ptr&lt;class T&gt;</code></h2>
24    </td>
25  </tr>
26</table>
27<hr>
28All the code snippets included below are defined within the
29<code style="white-space: normal">boost::serialization</code> namespace.
30<p>
31<code style="white-space: normal">shared_ptr&lt;T&gt;</code> is defined in
32<a href="../../../boost/shared_ptr.hpp" target=shared_ptr.hpp>shared_ptr.hpp</a>.
33<p>
34The general class outline for a <code style="white-space: normal">shared_ptr&lt;T&gt;</code> is:
35<dl>
36    <dt><code style="white-space: normal">shared_ptr&lt;T&gt;</code> contains:
37    <dl>
38        <dt><code style="white-space: normal">T *px;</code>
39        <dt><code style="white-space: normal">shared_count pn;</code> which contains a pointer to:
40        <dl>
41            <dt><code style="white-space: normal">sp_counted_base_impl&lt;T, ...&gt;</code> which is
42derived from the polymorphic abstract class
43            <dl>
44                <dt><code style="white-space: normal">sp_counted_base</code>
45            </dl>
46        </dl>
47    </dl>
48</dl>
49The serialization process proceeds down the tree above.
50<p>
51The first cut at implementing serialization for <code style="white-space: normal">shared_ptr</code>
52just serializes the relevant members of <code style="white-space: normal">shared_ptr</code>.
53It's almost trivial:
54<pre><code>
55template&lt;class Archive, class T&gt;
56inline void serialize(
57    Archive &amp; ar,
58    shared_ptr&lt;T&gt; &amp; t,
59    const unsigned int file_version,
60    int
61){
62    ar &amp; t.px; // save the raw pointer
63    ar &amp; t.pn; // save the shared reference count
64}
65</code></pre>
66So far so good.  Now for the serialization of <code style="white-space: normal">shared_count</code>:
67<pre><code>
68template&lt;class Archive&gt;
69inline void save(
70    Archive &amp; ar,
71    const boost::detail::shared_count &amp; t,
72    const unsigned int file_version
73){
74    ar &lt;&lt; t.pi_;
75}
76
77template&lt;class Archive&gt;
78inline void load(
79    Archive &amp; ar,
80    boost::detail::shared_count &amp; t,
81    const unsigned int file_version
82){
83    ar &gt;&gt; t.pi_;
84}
85</code></pre>
86A key feature of this library is the ability to specify serialization
87of a class or template without changing the class or template declaration
88or definition.  This is referred to as <i>non-intrusive</i> serialization.
89<p>
90The <code style="white-space: normal">pi_</code>member of shared count is a pointer to an
91instance of <code style="white-space: normal">sp_counted_base_impl<T, ...></code>.  Since this class
92doesn't have a default constructor, serialization requires
93specification of the following overload:
94<pre><code>
95template&lt;class Archive, class P, class D>
96inline void save_construct_data(
97    Archive &amp; ar,
98    const boost::detail::sp_counted_base_impl<P, D> * t,
99    const unsigned int file_version
100){
101    // variables used for construction
102    ar &lt;&lt; t->ptr;
103    ar &lt;&lt; *t;
104}
105
106template<class Archive, class P, class D>
107inline void load_construct_data(
108    Archive &amp; ar,
109    boost::detail::sp_counted_base_impl<P, D> * t,
110    const unsigned int file_version
111){
112    P ptr_;
113    ar &gt;&gt; ptr_;
114    // placement new
115    ::new(t)boost::detail::sp_counted_base_impl<P, D>(ptr_,  D());
116    ar &gt;&gt;; *t;
117}
118</code></pre>
119The statement <code style="white-space: normal">ar &gt;&gt; ptr_</code> is key. This deserializes
120the same pointer deserialzed above.  Default object tracking will ensure
121that no more than one instance of the object is created and that the
122pointer returned by multiple deserializations are all the same. Hence,
123regardless of how many instances of <code style="white-space: normal">shared_ptr/shared_count</code>
124corresponding to a particular object are created, the will all point
125to the same object.
126<p>
127Since <code style="white-space: normal">sp_counted_base_impl&lt;P, D&gt;</code> is derived from
128<code style="white-space: normal">sp_counted_base</code>, the following is needed:
129
130<pre><code>
131template&lt;class Archive, class P, class D&gt;
132inline void serialize(
133    Archive &amp; ar,
134    boost::detail::sp_counted_base_impl&lt;P, D&gt; &amp; t,
135    const unsigned int file_version,
136    int
137){
138    ar & boost::serialization::base_object&lt;
139        boost::detail::sp_counted_base
140    &gt;(*this);
141}
142</code></pre>
143which will in turn require serialization of its base class:
144<pre><code>
145inline void serialize(
146    Archive &amp; ar,
147    boost::detail::sp_counted &amp; t,
148    const unsigned int file_version,
149    int
150){
151}
152</code></pre>
153It would seem we're done, running the test program,
154<a href="../example/demo_shared_ptr.cpp" target="demo_shared_ptr_cpp">
155demo_shared_ptr.cpp
156</a>,
157with this code produces the following output.
158<pre><code>
159a = 0x003017A0 use count = 2
160a1 = 0x003017A0 use count = 2
161unique element count = 1
162a = 0x00000000 use count = 0
163a1 = 0x00000000 use count = 0
164unique element count = 0
165a = 0x00303060 use count = 1
166a1 = 0x00303060 use count = 1
167unique element count = 1
168</code></pre>
169This indicates that we're not quite done.  Due to default object
170tracking, <code style="white-space: normal">sp_counted_base_impl&lt;P, D&gt;</code> is only
171created once regardless of how many shared pointers point to the
172same object.  Of course, it has to be this way. The reference
173count starts at 1 and is never incrememented.  Code must be added
174to the serialization functions to maintain the proper reference
175count.
176<p>
177The process of serialization of an empty base class -
178<code style="white-space: normal">sp_counted_base</code> - seems like additional overhead.
179Examination of code in
180<a href="../../../boost/serialization/base_object.hpp" target="base_object_hpp">
181base_object.hpp
182</a>
183reveals that <code style="white-space: normal">base_object.hpp</code> provides two functions:
184<ul>
185    <li>invokes serialization of the base class data
186    <li>as a side effect, "registers" the fact base/derived relationship
187so that conversions of pointers between base and derived classes can be
188made at runtime.
189</ul>
190In this case we need only the latter function so we can replace the
191base object serialization with:
192<pre><code>
193// register the relationship between each derived class
194// its polymorphic base
195void_cast_register&lt;
196    boost::detail::sp_counted_base_impl&lt;P, D&gt;
197    boost::detail::sp_counted_base,
198&gt;();
199</code></pre>
200and we don't have to include a trival serializer for <code style="white-space: normal">sp_counted_base</code>
201<p>
202Finally we need to specify name-value pair wrappers if we want to be able
203to use this serialization with XML archives.
204<p>
205Actually, even this is really just a start. Among the issues not addressed in
206this implementation are:
207<ul>
208    <li><code style="white-space: normal">weak_ptr</code> is not addressed.  I haven't even looked into this.
209    <li>Other smart pointers that might interact with <code style="white-space: normal">shared_ptr</code>
210    haven't been addressed at all.  To be confident that the implementation is
211    complete and correct, all these should be addressed as well.
212    <li>Exception handling hasn't been exhaustively considered.
213    <li>Other issues yet to be discovered.
214</ul>
215One thing that has been considered is export of shared_ptr. The header which
216declares shared pointer serialization includes some special macros for exporting
217shared pointers:
218<code><pre>
219BOOST_SHARED_POINTER_EXPORT(T)
220BOOST_SHARED_POINTER_EXPORT_GUID(T, K)
221</pre></code>
222These are specialize versions of the macros used for exporting classes serialized through raw pointers.
223<p>
224Clearly, complete, correct and exception safe serialization of smart pointers is going to
225be a challenge.  I hope that this implementation provides a useful
226starting point for such an effort.
227<hr>
228<p><i>&copy; Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004.
229Distributed under the Boost Software License, Version 1.0. (See
230accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
231</i></p>
232</body>
233</html>
Note: See TracBrowser for help on using the repository browser.