Dynamic references can be serialised, provided a few properties are known about the data structure they make up. There is no way of knowing whether standard pointer actually points to a real object, nor how many. However, since collections of objects are more conveniently handled by standard containers, and since no object can pointed to by the value 0 (or NULL), we can determine these things if the programmer follows a protocol whereby a pointer either references at a single object, or is NULL. Using a smart pointer additionally enforces this protocol. We call this the treenode or graphnode protocol, depending on whether the referenced data structure has cycles or not.
By default, packing a pointer raises an exception. However, this
behavior is changed either by specifying a given type obeys the
treenode or graphnode protocol using the treenode
pragma or graphnode pragma
respectively. Alternatively, the
pack_t::ptr_flag can be set to
What happens in this case, is that special graph serialisation
algorithms defined in
pack_graph.h are called that ensure graph
objects are serialised or deserialised correctly. For deserialisation,
new objects must be created to store the node contents. References to
these objects are placed in the
pack_t buffer object. These newly created objects are
destroyed when the buffer object is destroyed, unless a copy of the
alloced vector is made first. Conversely, the objects can be
destroyed without destroying the buffer by clearing the alloced
vector. Individual objects can be destroyed by simply erasing them
(assuming you know which ones!).
pack_graph is a recursive depth-first algorithm, that could
potentially blow up the stack if the recursion depth is not
limited. The recursion limit can be specified using
pack_t::recur_max. pack_graph restarts the
algorithm once the recursion limit is reached.
pack_graph algorithm can also be applied to smart pointers
or other reference types. An example is the
ref smart pointer
provided with Classdesc. For your smart pointer class T, you will need to provide an
class with an
operator()(pack_t* buf, T& x) that returns a
newly allocated object referenced by x. The
buf object is there
if you wish to use the alloced mechanism.