Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2004-11-18 07:21:05


Robert Ramey wrote:
> I thought about a little more. If I rememeber correctly the essense
> of the problem during de-serialization was:
>
> template<class Archive, class T>
> void serialize(Archive &ar, shared_ptr<T> & t){
> T * raw_ptr;
> ar >> raw_ptr;
> t = shared_ptr(raw_ptr); // problem is here - not matched with
> other shared pointers that might point to raw_ptr
> // current shared_ptr implementation depends upon an internal
> pointer to
> a shared count.
> }

No, the problems lie elsewhere. The pseudocode of the deserializer is as
follows:

typedef std::map< int, shared_ptr<void> > load_sp_map;

template<class Archive, class T> void load(Archive & ar, shared_ptr<T> & t)
{
    int pid;
    ar >> pid;

    if( pid == 0 )
    {
        t.reset();
    }
    else
    {
        load_sp_map & map = get_load_sp_map( ar ); // #1

        if( map.count(pid) )
        {
            t = convert_from_derived_to_T( map[pid] ); // #2
        }
        else
        {
            Derived * p; // #3
            ar >> p;
            shared_ptr<T> tmp( p );
            t = p;
            map[pid] = p;
        }
    }
}

The line marked #1 is a general problem with the library, there is no way to
associate user data with an archive, and some types require it.

The lines marked #2 and #3 come into play when the actual pointer that was
serialized was

    shared_ptr<T> t( new Derived );

#3 is not doable without help from the library, because - if I understand
correctly - only the library knows how the type of a polymorphic object is
stored in the archive. IOW the external representation is opaque, an
"implementation detail".

#2 is a problem because map[pid] was read in a previous call to load by #3
and points to some type that is not necessarily T.

> Attempts to resolve this all ended up re-implementing some aspect of
> the serialization library.

Indeed.

> I didn't really consider modifying the library to expose the relevant
> aspects
> IT'S implementation. That would entail much more than changing a private
> to public or adding a friend.

Maybe, but perhaps this would help others that are faced with a similar
problem?

> As far as
> I was concerned - implementing the the library once was enough. The
> implementation I made is straight forward and is compatible with all
> aspects of the serialization library including exported pointers,
> pointers to polymorphic base classes, non-default and private
> constructors - everything.
>
> So maybe we can consider a practical compromise.
>
> a) Grant me access to the internals of shared_ptr for now

a) You aren't going to get access to the internals of std::tr1::shared_ptr.

b) Your implementation doesn't work when a weak_ptr is read before the
corresponding shared_ptr.

c) I "reserve the right to" change the implementation of boost::shared_ptr.
IIUC with this implementation this will break every data file that contains
a boost::shared_ptr. Correct?


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