X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fstlplus%2Fpersistence%2Fpersistent_smart_ptr.tpp;fp=src%2Fstlplus%2Fpersistence%2Fpersistent_smart_ptr.tpp;h=2ce531577d5f428ada0d16ade38318f94c333912;hb=6b0a0d0efafe34d48ab344fca3b479553bd4e62c;hp=0000000000000000000000000000000000000000;hpb=85783316365181491a3e3c0c63659972477cebba;p=chaz%2Fyoink diff --git a/src/stlplus/persistence/persistent_smart_ptr.tpp b/src/stlplus/persistence/persistent_smart_ptr.tpp new file mode 100644 index 0000000..2ce5315 --- /dev/null +++ b/src/stlplus/persistence/persistent_smart_ptr.tpp @@ -0,0 +1,176 @@ +//////////////////////////////////////////////////////////////////////////////// + +// Author: Andy Rushton +// Copyright: (c) Southampton University 1999-2004 +// (c) Andy Rushton 2004-2009 +// License: BSD License, see ../docs/license.html + +//////////////////////////////////////////////////////////////////////////////// +#include "persistent_int.hpp" +#include "persistent_pointer.hpp" +#include "persistent_callback.hpp" +#include "persistent_interface.hpp" + +namespace stlplus +{ + + //////////////////////////////////////////////////////////////////////////////// + + template + void dump_smart_ptr(dump_context& context, const smart_ptr& data, + DE dump_element) + throw(persistent_dump_failed) + { + // similar to the simple pointer routines, but use the address of the holder to tell which objects are aliases + // Many smart pointers can point to the same object. + // I could have used the address of the object to differentiate, + // but that would not have differentiated between different null smart pointers + // so I use the address of the substructure to differentiate between different objects. + // get a magic key for the substructure - this also returns a flag saying whether its been seen before + std::pair mapping = context.pointer_map(data._handle()); + // dump the magic key + dump_unsigned(context,mapping.second); + // dump the contents but only if this is the first time this object has been seen + // use the existing routines for ordinary pointers to dump the contents + if (!mapping.first) + dump_pointer(context,data.pointer(),dump_element); + } + + template + void restore_smart_ptr(restore_context& context, smart_ptr& data, + RE restore_element) + throw(persistent_restore_failed) + { + // get the old substructure magic key + unsigned magic = 0; + restore_unsigned(context,magic); + // lookup this magic number to see if we have seen this already + std::pair mapping = context.pointer_map(magic); + if (mapping.first) + { + // this holder has already been restored + // dealias the existing holder and replace it with the seen-before holder to make this object an alias of it + data._make_alias((smart_ptr_holder*)mapping.second); + } + else + { + // this is the first contact with this holder + // make sure this smart pointer is unique to prevent side-effects + data.clear_unique(); + // map the magic key onto this structure's holder + // do this before restoring the object so that self-referential structures restore correctly + context.pointer_add(magic,data._handle()); + // now restore the object + T* value = 0; + restore_pointer(context,value,restore_element); + data.set(value); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // smart_ptr_clone using callbacks + + template + void dump_smart_ptr_clone_callback(dump_context& context, const smart_ptr_clone& data) + throw(persistent_dump_failed) + { + // similar to the simple pointer routines, but use the address of the holder to tell which objects are aliases + // Many smart pointers can point to the same object. + // I could have used the address of the object to differentiate, + // but that would not have differentiated between different null smart pointers + // so I use the address of the substructure to differentiate between different objects. + // get a magic key for the substructure - this also returns a flag saying whether its been seen before + std::pair mapping = context.pointer_map(data._handle()); + // dump the magic key + dump_unsigned(context,mapping.second); + // dump the contents but only if this is the first time this object has been seen + // use the existing routines for ordinary pointers to dump the contents + if (!mapping.first) + dump_callback(context,data.pointer()); + } + + template + void restore_smart_ptr_clone_callback(restore_context& context, smart_ptr_clone& data) + throw(persistent_restore_failed) + { + // get the old substructure magic key + unsigned magic = 0; + restore_unsigned(context,magic); + // lookup this magic number to see if we have seen this already + std::pair mapping = context.pointer_map(magic); + if (mapping.first) + { + // this holder has already been restored + // dealias the existing holder and replace it with the seen-before holder to make this object an alias of it + data._make_alias((smart_ptr_holder*)mapping.second); + } + else + { + // this is the first contact with this holder + // make sure this smart pointer is unique to prevent side-effects + data.clear_unique(); + // map the magic key onto this structure's holder + // do this before restoring the object so that self-referential structures restore correctly + context.pointer_add(magic,data._handle()); + // now restore the object + T* value = 0; + restore_callback(context,value); + data.set(value); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // smart_ptr_clone using interface + + template + void dump_smart_ptr_clone_interface(dump_context& context, const smart_ptr_clone& data) + throw(persistent_dump_failed) + { + // similar to the simple pointer routines, but use the address of the holder to tell which objects are aliases + // Many smart pointers can point to the same object. + // I could have used the address of the object to differentiate, + // but that would not have differentiated between different null smart pointers + // so I use the address of the substructure to differentiate between different objects. + // get a magic key for the substructure - this also returns a flag saying whether its been seen before + std::pair mapping = context.pointer_map(data._handle()); + // dump the magic key + dump_unsigned(context,mapping.second); + // dump the contents but only if this is the first time this object has been seen + // use the existing routines for ordinary pointers to dump the contents + if (!mapping.first) + dump_interface(context,data.pointer()); + } + + template + void restore_smart_ptr_clone_interface(restore_context& context, smart_ptr_clone& data) + throw(persistent_restore_failed) + { + // get the old substructure magic key + unsigned magic = 0; + restore_unsigned(context,magic); + // lookup this magic number to see if we have seen this already + std::pair mapping = context.pointer_map(magic); + if (mapping.first) + { + // this holder has already been restored + // dealias the existing holder and replace it with the seen-before holder to make this object an alias of it + data._make_alias((smart_ptr_holder*)mapping.second); + } + else + { + // this is the first contact with this holder + // make sure this smart pointer is unique to prevent side-effects + data.clear_unique(); + // map the magic key onto this structure's holder + // do this before restoring the object so that self-referential structures restore correctly + context.pointer_add(magic,data._handle()); + // now restore the object + T* value = 0; + restore_interface(context,value); + data.set(value); + } + } + + //////////////////////////////////////////////////////////////////////////////// + +} // end namespace stlplus