|
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