    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: A Simple Model for Object Persistence Using the Standard
Library</title>
        <link>https://members.accu.org/index.php/articles/531</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Design of applications and programs + Overload Journal #32 - Jun 1999</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c67/">Design</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c172/">32</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c67-172/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c67+172/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;A Simple Model for Object Persistence Using the Standard
Library</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 26 June 1999 17:50:53 +01:00 or Sat, 26 June 1999 17:50:53 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="abstract">
<p class="title c1">Abstract</p>
<p>Serialising systems of objects poses some challenges in terms of
the preservation of inter-object associations, and object id
allocation and management. For a large-scale project, heavyweight
databases are the accepted solution, but for smaller projects
simpler homegrown solutions are possible. I present one such system
here.</p>
</div>
<div class="titlepage">
<h2><a name="d0e23" id=
"d0e23"></a>Introduction</h2>
</div>
<p>There are many possible requirements for a persistence
framework. Persistence could involve object load on demand, cross
platform support, multithreaded or multiprocess access, robust
transactional storage, etc., etc. This article covers none of these
issues. Instead, I shall focus on the bottom line: preserving a
system of objects, along with their interconnections, to permanent
storage, with a view to restoring the entire system to memory at a
later date.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e28" id="d0e28"></a>Single
Objects</h2>
</div>
<p>Serialising simple attribute types is easy. We can pretty much
take the memory image of such data and copy it verbatim to disk.
This reversible process allows the data to be restored just as
easily (see figure 1).</p>
<div class="figure"><a name="d0e33" id="d0e33"></a>
<div class="mediaobject c3"><img src=
"/var/uploads/journals/resources/Blundell%20_fig1.png" align="middle" alt=
"Simple attributes are easy to serialise."></div>
<p class="title c1">Figure 1. Simple attributes are easy to
serialise.</p>
</div>
<p>Although more complex objects typically contain simple attribute
types, they are more difficult to serialise because they may
contain links to other objects. These links are often represented,
in one way or another, as pointers or disguised pointers (smart
pointers, look-up tables, etc.). Pointers provide extremely
efficient and low-level access to the pointee, but they suffer from
the problem that their values are not preserved across successive
incarnations of an application.</p>
<p>Thus, association information needs special handling in any
persistence framework. We need to be able to identify the object
pointed to in an invariant manner in order to store it to disk and
unambiguously restore it again (see figure 2).</p>
<div class="figure"><a name="d0e43" id="d0e43"></a>
<div class="mediaobject c3"><img src=
"/var/uploads/journals/resources/Blundell%20_fig2.png" align="middle" alt=
"Associations needs to be preserved when serialising interconnected objects."></div>
<p class="title c1">Figure 2. Associations needs to be preserved
when serialising interconnected objects.</p>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e49" id="d0e49"></a>Object Ids
(OIDs)</h2>
</div>
<p>One way to manage object references is to allocate each object a
unique object ID (OID). If each object (or each object of a given
type) can be uniquely referenced using its OID, and if these OIDs
are stored to file when the system is persisted, then the
pointer-based object associations can be calculated when restored
by using a look-up table mapping IDs to objects.</p>
<p>The drawback is that allocating and managing these OIDs can be
tricky and expensive.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e56" id="d0e56"></a>ID
Management</h2>
</div>
<p>There are many different techniques for allocating IDs to
objects. If the total number of objects ever created is small, you
can just give objects successive integer values. All you need to do
is keep track of the last ID allocated, and allocate the following
one next time. You need to be careful that frequently allocated
temporary objects don't exhaust the range of IDs and cause the
allocated IDs to 'wrap around.'</p>
<p>Alternatively, you can create and manage a pool of available
IDs, and allocate them from the pool, returning IDs to the pool as
their owners expire. This is less time-efficient, and can also
impose a larger memory overhead, but is a more robust solution for
a long-lived application.</p>
<p>Object factories can simply create objects with IDs when
requested, or they can additionally keep track of the objects
themselves, allowing an object to be located given only its ID. In
this case it is useful to make the factory responsible for
destroying objects as well, in order to preserve the integrity of
the ID pool.</p>
<p>OIDs are just a resource, and depending upon the scheme
employed, typical resource management dangers can arise. There may
be no way to determine if a given OID is valid or not. You must
plan to handle exhausting your pool of IDs. Unless resources are
managed carefully (or automatically, perhaps with some form of
'smart' references) you could leak OIDs (a handle leak) by not
releasing expired IDs, or you could get 'dangling IDs' instead of
dangling pointers, if references are not correctly updated.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e67" id="d0e67"></a>Commercial
Databases</h2>
</div>
<p>One way to manage ID allocation as well as persistence is to use
a commercial database of some sort. If you create a mapping between
your objects and a RDBMS, the database can manage the allocation of
unique ids that serve as primary keys for each table of objects, as
well as the physical storage and retrieval of the objects' data,
their integrity, backup, sharing, replication, etc. These days an
OODBMS can be used, which will additionally save you mapping your
objects to flat tables.</p>
<p>But where's the challenge in that?! &#9786; And besides, for
small projects, or where a database system or its associated
distributable runtime are unavailable or unsuitable, this may not
be an option (or at least not the first choice). So let's see if we
can get some way towards a simple solution ourselves.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e74" id="d0e74"></a>The Ideal
Object ID</h2>
</div>
<p>Let's consider OIDs again, because referencing objects is the
crux of the persistence problem. An ideal OID should be unique
between objects. If it were additionally unique between classes of
objects then that might be a 'nice-to-have.' We need quick and
efficient access to an object via its OID. We also require a large
pool of OIDs to ensure that we never run out of them. Efficient
reuse of OIDs is necessary so that OIDs that are no longer needed
can be recycled effectively. Finally, they need to be invariant
over serialisation.</p>
<p>Sounds like a tall order. But what about memory pointers? They
fulfil all these requirements apart from the fact that they are not
preserved during serialisation - i.e. an object's '<tt class=
"varname">this</tt>' pointer is not the same when you reload it
from disk.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e84" id="d0e84"></a>Pointers?</h2>
</div>
<p>In order to serialise a system to disk and then restore it again
at a later date, all we need to do is to store the original pointer
values to disk. These uniquely identify the original objects
pointed to. The trick is that we then need to re-map the object
associations when we load them back, in order to match pointers
with the correct objects, and all will be well!</p>
<p>We can't, in general, specify the <tt class="varname">this</tt>
pointer of an object when it is created, so we must re-map the
pointers <span class="emphasis"><em>to</em></span> each object -
the source, not the target, end of each association.</p>
<p>John Merrells suggested mangling the pointer values as we
serialise them (and unmangling them as we restore them) so they
look less like memory pointers during debugging. It is easy to
incorporate this.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e99" id="d0e99"></a>Persistence
Using Pointers - the Details</h2>
</div>
<p>To save a system to file, we must save each object, complete
with the mangled pointer values for all the other objects to which
it points. In addition to this, every object that can be pointed to
must save its current <tt class="varname">this</tt> pointer
(similarly mangled).</p>
<p>As our objects come back in from file, we note the original
mangled <tt class="varname">this</tt> pointer for each object from
the last time it was in memory, and the new <tt class=
"varname">this</tt> pointer for the current incarnation of the
object, and store this mapping in a look-up table. Then, for every
pointer we read in from file, we simply read the map to find the
new location of the referenced object. This also unmangles the
pointers' values automatically.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e115" id="d0e115"></a>Pointers to
the Future</h2>
</div>
<p>That might sound easy so far, but there's one more problem
awaiting us. At the point that we read in an object, it is quite
possible (quite likely in fact) that some of the other objects that
it references have not yet been restored. We therefore do not yet
know what their new memory locations are. An obvious example of
this is a circular reference, in which one pointer is guaranteed to
point to a future object. In general, however, you can get this
problem without any explicit circular references. In these
situations, careful scheduling of the streaming of the objects to
disk can avoid all cases of references to future objects, but for
complex systems it is often not trivial, or even possible, to
determine such an order.</p>
<div class="figure"><a name="d0e120" id="d0e120"></a>
<div class="mediaobject c3"><img src=
"/var/uploads/journals/resources/Blundell%20_fig3.png" align="middle" alt=
"A complex system of interconnected objects, including cyclical navigable associations."></div>
<p class="title c1">Figure 3. A complex system of interconnected
objects, including cyclical navigable associations.</p>
</div>
<p>To solve this we need a two-stage procedure to mirror the two
operations we are performing.</p>
<div class="orderedlist">
<ol type="i">
<li>
<p>Load in the objects, and</p>
</li>
<li>
<p>Patch up the pointers.</p>
</li>
</ol>
</div>
<p>There are a number of ways to achieve this.</p>
<p>We could have two explicit calls to each object in order to
restore it from disk - one to load all its non-pointer data and map
old to new <tt class="varname">this</tt> pointers, and the other
(called after all objects have been constructed) to patch up
pointer references. At the point of the second pass, all objects
have been created, and so all pointers can be patched up.</p>
<p>Another way to do this would be to simply create all the objects
in pass one, and in pass two serialise all the objects' attributes
- pointer and non-pointer alike.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e144" id="d0e144"></a>Queuing
Association Requests</h2>
</div>
<p>A less obtrusive procedure is to automatically patch up
associations from outside of the objects. This allows a single
serialisation pass for each object, which is more common in typical
serialisation schemes. We can reload all the objects, complete with
their original attributes and pointer values (mangled), and then
have an external serialisation manager correct all the inter-object
associations at the end,1 without the objects' knowledge. This is
quite a neat solution, but does rely on none of the objects
exercising any of their associations before the end of
serialisation (which can usually be arranged).</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e149" id="d0e149"></a>Will it
Fly?</h2>
</div>
<p>So, does this work in practice? Well, I got it to work quite
simply, and this is what I did.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e154" id="d0e154"></a>The Object
Map - Mapping '<tt class="varname">this</tt>' Pointers</h2>
</div>
<p>First, we need some form of map for mapping the old to the new
<tt class="varname">this</tt> pointer values. For this I created a
class called <tt class="classname">object_map</tt>:</p>
<pre class="programlisting">
class object_map
{
public:
   void register_object(void *old_this,
                        void *new_this); 
   bool lookup(void *old_ptr,
               void *&amp;new_ptr) const;
   void clear();

private:
   // ... (disable copying, etc.)
   typedef std::map&lt;void *, void *&gt; ptr_map;
   ptr_map  m_pointer_map;
};
</pre>
<p>This is a concrete class that just manages a pointer-to-pointer
map. I'm mapping <tt class="type">void *</tt> pointers here because
all pointers can safely be cast to this type and back on any
platform. The pointer values also have to be stored to disk anyway,
and so if they have just come back from disk, a <tt class=
"type">void *</tt> is as good a type as any in which to hold
them.</p>
<p>As each object is loaded, its previous this pointer is read in
and mapped to its current this pointer value using the <tt class=
"methodname">register_object()</tt> method. At a later date, if
another object wants to point to this one, it calls <tt class=
"methodname">lookup()</tt> with its previous pointer value, and the
latest pointer value is returned, if present.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e186" id="d0e186"></a>The Request
Queue - Handling Future Objects</h2>
</div>
<p>The next thing we need to do is handle all those future object
references. For this I created a class called <tt class=
"classname">request_queue</tt> to 'queue-up' all the pending map
requests that could not be fulfilled in the first instance.</p>
<pre class="programlisting">
class request_queue
{
public:
   template &lt;typename T&gt;
   push_request(T *&amp;pointer);

   void map_unmapped(object_map &amp;om);
   void clear();

private:
   // ...
   std::stack&lt;map_request *&gt; m_requests;
};
</pre>
<p>This class manages a bunch<sup>[<a name="d0e198" href=
"#ftn.d0e198" id="d0e198">1</a>]</sup> of pending requests.
Pointers that need mapping are added to the queue with the
<tt class="methodname">push_request()</tt> template method. At the
end of serialisation, the <tt class=
"methodname">map_unmapped()</tt> method is called, which processes
all the queued requests, patching up all the pointers.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e208" id="d0e208"></a>Map Requests
for Different Pointer Types</h2>
</div>
<p>So, how are all these pointers, all of different types, held in
the request queue? I wanted to hold their types as well as their
values (rather than casting them all to <tt class="type">void
*</tt>s) so that they can be patched up correctly. Remember that
objects may hold base class pointers to objects of derived types,
and we need to ensure that any necessary pointer conversions are
handled correctly. To do this, I utilised the external polymorphism
pattern. This pattern allows types that have no polymorphic
relationship (like our pointers) to be treated polymorphically.</p>
<p>I created an interface that I called <tt class=
"classname">map_request</tt>. I needed to store a whole bunch of
outstanding requests in the <tt class=
"classname">request_queue</tt> container, yet I wanted to preserve
the type information for each one. In other words, I wanted to
store a request to map a pointer to a <span class=
"emphasis"><em>wotsit</em></span> in the same container that I
store a request to map a pointer to a <span class=
"emphasis"><em>thingamy</em></span>. If I imposed a common base
class on all objects, then I would be home and dry, but in general,
<span class="emphasis"><em>wotsits</em></span> won't be related to
<span class="emphasis"><em>thingamies</em></span> by any normal
inheritance relationship. The way the external polymorphism pattern
works is by defining a base class or interface, and then deriving
classes from this base class for each of the types you want to
handle.</p>
<p>The <tt class="classname">map_request</tt> interface looks like
this:</p>
<pre class="programlisting">
class map_request
{
public:
   virtual ~map_request() {}

   virtual void *old_this() const = 0;
   virtual void map_to(void *new_this) = 0;
};
</pre>
<p>Request objects (those derived from <tt class=
"classname">map_request</tt>) store the previous location of the
pointer, along with its type, and allow the pointer value at this
location to be queried and set. A template class handles pointers
to all types we could ever want in one fell swoop:</p>
<pre class="programlisting">
template &lt;typename T&gt;
class map_request_type : public map_request
{
public:
   explicit map_request_type(T *&amp;ptr)
      : m_ptr(ptr)   {}

   virtual void *old_this() const
      {return m_ptr;}
   virtual void map_to(void *new_this)
      {m_ptr = static_cast&lt;T *&gt;(new_this);}

private:
   T   *&amp;m_ptr;
};
</pre>
<p>If you have an object of type <tt class=
"classname">map_request_type&lt;T&gt;</tt>, the <tt class=
"methodname">old_this()</tt> method allows the current pointer
value to be accessed for look-up purposes, and the <tt class=
"methodname">map_to()</tt> method casts the <tt class="type">void
*</tt> pointer passed in to the correct type, in this case a
pointer to type <tt class="type">T</tt>. This is a safe cast
because we know the static type of the pointer (i.e. at compile
time).</p>
<p>The procedure for saving a pointer to file is thus</p>
<div class="orderedlist">
<ol type="i">
<li>
<p>Cast the <tt class="type">T *</tt> pointer to a <tt class=
"type">void *</tt> pointer.</p>
</li>
<li>
<p>Store this void * pointer to disk.</p>
</li>
</ol>
</div>
<p>To reload the pointer from file we do this:</p>
<div class="orderedlist">
<ol type="i">
<li>
<p>Read the <tt class="type">void *</tt> pointer from file.</p>
</li>
<li>
<p>Look up <tt class="varname">this</tt> pointer value in the
map.</p>
<div class="orderedlist">
<ol type="a">
<li>
<p>If present, cast the pointer value to a <tt class="type">T
*</tt> pointer and use that pointer value.</p>
</li>
<li>
<p>If the pointer is not present in the map, create a <tt class=
"classname">map_request_type</tt> object of the correct type, and
add it to the queue.</p>
</li>
</ol>
</div>
</li>
<li>
<p>At the end of serialisation, repeat step (ii) alone on all the
pending pointers in the queue.</p>
</li>
</ol>
</div>
<p>This process avoids a lot of unnecessary and dangerous casts in
client code. It also ensures that if a base pointer is used to
reference a derived object, the correct pointer conversions will be
applied, and the pointer values adjusted accordingly.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e315" id="d0e315"></a>Mangling
Pointer Values</h2>
</div>
<p>In order to mangle the pointer values as they are saved to disk,
and unmangle them if required when they are restored, I created the
<tt class="classname">pointer_mangler</tt> class:</p>
<pre class="programlisting">
class pointer_mangler
{
public:
   explicit pointer_mangler(
      unsigned long mangle_style = ~0UL)
     : m_style(mangle_style)   {}

   void *mangle(void *ptr) const;
   void *unmangle(void *ptr) const;

private:
   unsigned long m_style;
};
</pre>
<p>This class simply mangles <tt class="type">void *</tt> pointers.
The ctor has a parameter that allows you to specify how pointers
are to be mangled. In principle this would allow different pointer
types to be mangled in different ways, if required for debugging
purposes, by using a range of different <tt class=
"classname">pointer_mangler</tt> objects. My implementation simply
casts the pointers to unsigned longs, and xors the result with the
style value. It is therefore symmetric, with <tt class=
"methodname">mangle()</tt> doing the same thing as <tt class=
"methodname">unmangle()</tt><sup>[<a name="d0e338" href=
"#ftn.d0e338" id="d0e338">2</a>]</sup>.</p>
<p>Note that this class is platform dependent, and assumes a
<tt class="type">void *</tt> pointer can be cast to an unsigned
long and back without loss of information (which I imagine should
be true in most cases).</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e350" id="d0e350"></a>The
Persistence Manager</h2>
</div>
<p>I brought the main classes together in the <tt class=
"classname">persistence_manager</tt> class:</p>
<pre class="programlisting">
class persistence_manager
{
public:
   void initialise();
   bool terminate();

public:
   void register_me(void *old_this,
                    void *new_this);

   template &lt;typename T&gt;
   void unpersist_pointer(T *&amp;pointer);

private:
   // no copying, etc...
   object_map     m_object_map;
   request_queue  m_requests;
};
</pre>
<p>This class contains an object_map and a <tt class=
"classname">request_queue</tt>. The idea is that, at the start of
serialisation you create an instance of this class. For each object
that you read in, you register it using the <tt class=
"methodname">register_me()</tt> method, passing its previous and
current this pointers. Every pointer that you come across is
deserialised using the <tt class=
"methodname">unpersist_pointer()</tt> method. This template method
looks up the pointer in the map, and adjusts its value as
necessary. If it is not found in the map, it pushes a request onto
the <tt class="classname">request_queue</tt> and then continues. At
the end of serialisation, you call the <tt class=
"methodname">terminate()</tt> method, which then processes the
pending requests in the queue.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e377" id="d0e377"></a>A
Serialisation Example using <tt class=
"classname">fstream</tt>s</h2>
</div>
<p>Finally, to combine this class with a particular serialisation
method, as an example, I created the following persistence class.
This class is responsible for containing the <tt class=
"classname">persistence_manager</tt> object, the persistence stream
and a <tt class="classname">pointer_mangler</tt> object:</p>
<pre class="programlisting">
class persistence
{
public:
   explicit persistence(std::ofstream &amp;os);
   explicit persistence(std::ifstream &amp;is);
   ~persistence();

   // Example serialisation for ints
   // Could use insertion/extraction
   //  operator overloading if preferred
   void persist_int(int &amp;val);
   // Add other common types too&hellip;

   // persist this pointer
   void persist_me(void *my_this);

   // persist inter-object association
   template &lt;typename T&gt;
   void persist_pointer(T *&amp;pointer);

private:
   // Low-level void * serialisation
   // Handle pointer mangling, etc.
   void write_pointer(void *ptr);
   void *read_pointer();

private:
   persistence_manager  m_persist;
   pointer_mangler      m_mangler;
   std::ios             *m_pStream;
   bool                 m_saving;
};
</pre>
<p>I killed two birds with one stone here and made the class handle
both saving and loading. This allows the serialisation methods of
persistent objects to be simpler. A class diagram for this
arrangement is shown in figure 4. The basic idea is as follows.
When storing an object:</p>
<div class="orderedlist">
<ol type="i">
<li>
<p>If the object can be pointed to, use the <tt class=
"methodname">persist_me()</tt> method to store the current this
pointer to stream as a mangled <tt class="type">void *</tt>.</p>
</li>
<li>
<p>Store attributes to the stream as usual.</p>
</li>
<li>
<p>Store pointers to other objects using the <tt class=
"methodname">persist_pointer()</tt> method, which stores pointers
as mangled <tt class="type">void *</tt>s.</p>
</li>
</ol>
</div>
<p>When reloading the object, we use the following procedure:</p>
<div class="orderedlist">
<ol type="i">
<li>
<p>If the object can be pointed to, call <tt class=
"methodname">persist_me()</tt>. This now reads the previous this
pointer value from file as a <tt class="type">void *</tt>, and
registers the object's current location in the object map.</p>
</li>
<li>
<p>Read attributes from the stream as usual.</p>
</li>
<li>
<p>Re-establish object associations using the <tt class=
"methodname">persist_pointer()</tt> method. This looks up the
object pointers in the object map, and lodges a request for that
object if it has not yet been restored.</p>
</li>
<li>
<p>The dtor of the persistence object calls <tt class=
"methodname">persistence_manager::terminate()</tt>, which processes
all pending requests.</p>
<div class="figure"><a name="d0e444" id="d0e444"></a>
<div class="mediaobject c3"><img src=
"/var/uploads/journals/resources/Blundell%20_fig4.png" align="middle" alt=
"The example persistence system."></div>
<p class="title c1">Figure 4. The example persistence system.</p>
</div>
</li>
</ol>
</div>
<p>This will probably be clearer from an example. If we have an
object to be serialised that looks like this:</p>
<pre class="programlisting">
class B
{
public:
   // ...
   void persist(persistence &amp;p);

private:
   int  m_b;
   A    *m_pA;
};
</pre>
<p>We can write its <tt class="methodname">persist()</tt> method
(which handles both saving and loading) as follows:</p>
<pre class="programlisting">
void B::persist(persistence &amp;p)
{
   p.persist_me(this);      (1)
   p.persist_int(m_b);      (2)
   p.persist_pointer(m_pA); (3)
}
</pre>
<p>Line 1 is necessary if this object can ever be pointed to by
another persistent object. When saving, it stores the this pointer
to file, and when loading it registers the object in the map. Line
2 saves and loads a simple attribute type. Line 3 stores a pointer
to file when saving, and reloads and re-maps that pointer when
loading. An example system of objects of types A and B can now be
stored and restored as follows:</p>
<pre class="programlisting">
void data::save(ostream &amp;os)
{
   persistence p(os);
   for (int i = 0; i &lt; 5; ++i) {
      a[i].persist(p);
      b[i].persist(p);
   }
}

void data::load(istream &amp;is)
{
   persistence p(is);
   for (int i = 0; i &lt; 5; ++i) {
      a[i].persist(p);
      b[i].persist(p);
   }
}
</pre>
<p>where a[0..4] and b[0..4] are objects of type A and B
respectively. It's as simple as that. Persistent classes A and B
neither have to share a common base class nor contain any special
data members in order to support serialisation. All they need is a
single symmetrical persistence method. They simply hand temporary
responsibility for their object associations over to the
persistence object and concentrate on what they do best - being A's
and B's!</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e467" id="d0e467"></a>Points to
Note</h2>
</div>
<p>If a particular class fails to register itself in the map, then
pointers to those objects cannot be corrected at the end of the
loading stage. If this happens, your <tt class=
"classname">persistence</tt> class may want to throw an exception,
and to avoid this happening, you can safely register all objects
even if they are never pointed to. It just produces a little more
storage overhead if you do this.</p>
<p>Note that in order for a pointer to be found, you must ensure
that the pointer is in the map. This may sound silly, but if you
have complex inheritance hierarchies, you must ensure that
different values for an object's <tt class="varname">this</tt>
pointer are all stored, depending on the static type of references
to the object. For simple inheritance they will usually be the
same, but for multiple inheritance and especially when you have
virtual base classes, you can find that the effective value of an
object's <tt class="varname">this</tt> pointer depends on the type
of the pointer used to access it. In general, and if in doubt, you
can always re-register a derived object even if a parent object has
already registered. If it is already in the map, it will just get
replaced, and if the object address is genuinely different from the
previous entry, then all your bases are covered.</p>
<p>Finally note that if you already have object IDs allocated to
all the objects you can point to, then you can use the above
framework in a slightly different arrangement. Instead of storing
pointers to file you can store the OIDs. When you register an
object, you can add the current this pointer to the <tt class=
"classname">object_map</tt> keyed on the OID instead of the
previous <tt class="varname">this</tt> pointer. Then, as each OID
comes in, you can look this up in the map instead, in order to
determine the location of the referenced object. This allows fast
pointer-based associations between objects, whilst utilising the
extant OIDs to persist these associations.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e491" id=
"d0e491"></a>Conclusion</h2>
</div>
<p>The persistence framework outlined above is limited to systems
that are loaded from and stored to file in one go. It should be
useful for simple systems, however, and should cope with arbitrary
inheritance hierarchies and arbitrary object association patterns
in an unobtrusive manner. With a little care, it can also be used
in systems using smart pointers for their object reference
mechanism of choice.</p>
</div>
<div class="footnotes"><br>
<hr class="c4" width="100">
<div class="footnote">
<p><sup>[<a name="ftn.d0e198" href="#d0e198" id=
"ftn.d0e198">1</a>]</sup> If they could not be done at the
time.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e338" href="#d0e338" id=
"ftn.d0e338">2</a>]</sup> Although in the current examples
<tt class="methodname">unmangle()</tt> is not used, as a convenient
side effect of the remapping process is to make unmangling
unnecessary.</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
