Boost logo

Boost :

From: Robert Ramey (ramey_at_[hidden])
Date: 2004-11-21 23:37:20


"Peter Dimov" <pdimov_at_[hidden]> wrote in message
news:002d01c4cfe2$96d92bf0$6501a8c0_at_pdimov2...
> Robert Ramey wrote:
> > I've concluded that serializing shared pointer only depending on the
> > std::tr1::shared_ptr interface isn't going to be possible within the
> > current serialization library. This will have to be handled via some
> > separate module.
>
> I'll try to come up with something. No timelines, though. There are some
> places where the library can be of assistance, but this can be done later
in
> a series of incremental improvements.
>
> I looked at the implementation of the serialization library. Quite
> complicated and remarkable in its own way. ;-) The root cause is, in my
> opinion, that you started off with something and then added features as
> requested. Had you started with the _requested features_ you might not
have
> needed to add the rest. Anyway, to get back to shared_ptr.
>
> The key points are:
>

> 2. The ability to upcast a shared_ptr<void>/type_info to another
> shared_ptr<void>/type_info.

I don't see why this is necessary

> The problem with this approach is that the deserialized shared_ptr<T> will
> contain a deleter that will attempt to destroy a T, whereas the original
may
> have had a deleter destroying a Derived.

>
> This can affect users if ~T is inaccessible or non-virtual or if T is
> incomplete.
>
> It is not possible to solve this without help from the library; basically,
> the T* deserializer (which internally operates with void*/type_info pairs)
> will need to be duplicated to return shared_ptr<T> (internally
> shared_ptr<void>/type_info).

I don't see why this is necessary. During deserialization - the shared_ptr
already exists - usually as a member variable of same data structure. Its
already been created with the appropriate deleter. If the current deleter
is different than the original - then its an issue to be addressed with
class versioning. In general, the serialization library presumes that the s
tructure being recovered is the same as that originally saved - any
differences are addressed through versioning.

> 5. The ability to downcast the deserialized shared_ptr<T> to
> shared_ptr<void> pointing to the most derived object.
>
> This can be done with dynamic_pointer_cast<void>.

I don't see why this is necessary. The library does the appropriate
downcasting of raw pointer. As far as I know there's no reason why a
share_ptr<T> can't have a raw_ptr which, though it points to a T, actually
corresponds to a derivation of T.

>
> The external representation of shared_ptr / weak_ptr is as demonstrated by
> the earlier example:
>
> - int pid;
> - (opt) T * px;
>
> where pid == 0 denotes an empty pointer, a newly seen pid denotes a new
> object and is followed by px, and an already seen pid denotes a reference
to
> an existing object.

I don't see why this is necessary. The library already correctly handles
null raw pointers.

> shared_ptr probably needs to be marked as "never track, unversioned" to
not
> clutter the archive, but I'm not sure what is the official serialization
> library policy regarding std:: types.

For std collections, the policy I've used has been:

a) unversioned - on the idea that std collections are "cast in stone".

Given the complexity of serialization of shared_ptr, the possibility that
its serialization may depend upon its implementation (at least for
boost::shared_ptr, and that you've reserved the right to change the
implementation) I think it would be prudent to leave it as the default - i.e
versioned. This only adds 1 integer per template instantiation per archive.
A small price to pay to maintain future readability.

b) tracking - default.

This means that instances are tracked if and only if anywhere in the program
the the type is serialized through a pointer. I wouldn't expect that to
happen so I expect the default would be just fine.

The only real issue as I see it is that of pointer mapping. Making an
archive derivation that includes the map would work fine - but I would hope
we could find something that doesn't require a special archive type to
serialize a specific data type. Perhaps we can permit one to register an
exit routine with an archive. Then when a map is created a deletere is
registered with the archive. I wouldn't be in love with this but I could
probably live with it.

The other thing I was thinking about was the possibility of adding access to
the tracking map for matching up de-serialized shared_ptrs. So far, I
haven't resolved this in my own mind - I'm still thinking about it. It's
probably a dead end.

Robert Ramey


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