Boost logo

Boost :

Subject: Re: [boost] Serialization of std::shared_ptr
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2011-02-16 18:25:44


On Wed, Feb 16, 2011 at 1:43 PM, Loïc Joly
<loic.actarus.joly_at_[hidden]> wrote:
> Le 16/02/2011 20:38, Emil Dotchevski a écrit :
>>
>> On Wed, Feb 16, 2011 at 5:20 AM, Loïc Joly
>> <loic.actarus.joly_at_[hidden]>  wrote:
>>>
>>> I'm using the std::shared_ptr provided with MSVC 2010. I'd like to be
>>> able
>>> to use boost.serialization to serialize some of those shared_ptrs. I
>>> could
>>> find an old thread stating that std::tr1::shared_ptr were not handled
>>> (and
>>> it looked impossible to make them work). Is the situation the same with
>>> std::shared_ptr?
>>
>> If serializing std::shared_ptr/weak_ptr is impossible then I must have
>> done the impossible in my serialization lib. :)3.
>
> You did not know it was impossible, so you did it :)

To be completely honest, shared_ptr serialization *in general* is not
possible. For example, a shared_ptr<int> might have been created by
aliasing, and might be pointing an int that is a member in a larger
object of user-defined type which is the thing that needs to be
serialized when the shared_ptr<int> is saved. You can't, in general,
get a pointer to that object from an int pointer. But if the
shared_ptr points an object of polymorphic type, then serialization is
possible.

> It looks like the implementation of the serialization of boost::shared_ptr
> has changed a lot since that time, and it might be possible to adapt it to
> std::shared_ptr. From what I understand, however, this serialization needs
> extra bookeeping which is currently stored inside of the archive class. So
> it looks like I have to define my own archive to be able to serialize
> std::shared_ptr. I'm gonna give a thought about that.

The main problem is that shared_ptr can be used in contexts where the
pointee type is incomplete, yet to write or read the object you need
to be able to call a function in which the type is complete. So you
need a registry of read and write functions. In addition, the
incomplete type you want to be reading or writing might in fact be a
base type (obviously you wouldn't know because it is incomplete), so
you need registration for functions that can do a static_cast from one
type to another (so you can get a derived pointer from your base
pointer.) In addition, to create an object when reading, you need a
registry with factory functions. In addition, in order to know if two
shared_ptrs point to the same object (of polymorphic type) you have to
use dynamic_cast<void *> but again, it needs to happen in a function
that the user defines and registers.

The bottom line is that you need a bunch of maps where types, casts,
and functions are registered, and ideally these maps should maintain
the lifetime of the entries correctly so that if a registration comes
from a dynamic library, when the library is unloaded the relevant
registrations are undone.

However, such requirements aren't unique for shared_ptr serialization.
In general when something is loaded or saved, the load and save
functions may need access to "manager" objects. For example, to load a
IDirect3DTexture9 object, the load function needs access to a
IDirect3DDevice9 object which is used to create the texture.
Therefore, the user must be able to associate arbitrary data (such as
a pointer to a IDirect3DDevice9) with any archive, so that load and
save functions can get to it from the archive object they take as an
argument. If such system exists, it can be used to store the maps
needed by the shared_ptr serialization as well.

Emil Dotchevski
Reverge Studios, Inc.
http://www.revergestudios.com/reblog/index.php?n=ReCode


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk