seiralization of shared_ptr

Some time ago the question was raised on this list as to why it was necessary to access share_count in order to implement serialization of shared_ptr. At the time I didn't have an answer. So I went back and tried to re-implement it and have come to the following point beyond which I can't proceed without manipulating shared_count directly. ///////////////////////////////////////////////////////////// // implement serialization for shared_ptr<T> template<class Archive, class T> inline void save( Archive & ar, const shared_ptr<T> & t, const unsigned int /* file_version */ ){ ar << boost::serialization::make_nvp("px", t.get()); } template<class Archive, class T> inline void load( Archive & ar, shared_ptr<T> & t, const unsigned int /* file_version */ ){ // object tracking guarantees that pointers are not replicated // on loading. T * t_new; ar >> boost::serialization::make_nvp("px", t_new); // if its not the first time, it should be equal to the current pointer assert(0 == t.use_count() || t.get() == t_new); // assign new pointer or bump reference count as appropriate // ???? - what goes here? } Can anybody tell me "what goes here?" Robert Ramey

"Robert Ramey" <ramey@rrsd.com> wrote in message news:20040519164342.3E2E03150B@acme.west.net...
Some time ago the question was raised on this list as to why it was necessary to access share_count in order to implement serialization of shared_ptr. At the time I didn't have an answer.
In recently debugging the serialization memory leak, I've come to the conclusion that it is necessary to serialize shared_count in particular it's sp_counted_base_impl<P,D>* _pi member. It is the 'shared' sp_counted_base_impl<P,D> that glues together the multiple instances of shared_ptr that refer to the same object. The serialization of sp_counted_base should then initialize use_count = 0, and weak_count = 1, there is no need to physically write/read to the file(which currently isn't done anyway). It appears to me that the shared_ptr<T>::px is not even structurally required, but is an optimization trading space to avoid an extra pointer dereference to the sp_counted_base_impl<P,D>::P member. Or have I missed something with my limited exposure? Modifying your previous implementation for shared_ptr<T> removing the serialization of px leads to the following. This assumes a couple of new methods on shared_count, and is untested. template<class Archive, class T> inline void serialize( Archive & ar, shared_ptr<T> &t, const unsigned int /* file_version */ ){ // correct shared_ptr serialization depends upon object tracking // being used. BOOST_STATIC_ASSERT( serialization::tracking_level<T>::value != serialization::track_never ); // only the raw pointer has to be saved // the ref count is maintained automatically as shared pointers are loaded ar.register_type(static_cast< boost::detail::sp_counted_base_impl<T *, boost::checked_deleter<T> > * >(NULL)); ar & boost::serialization::make_nvp("pn", t.pn); if( t.pn ) { if( !t.pn.is_managing_ptr( px ) ) { if( !px ) { t.pn.assign_managed_ptr( px ); // px = static_cast<T*>(t.pn.P) } // calls add_ref_copy() else { // ???error memory leak } } } else { // could be serializing a NULL shared_ptr } } This still leaves your existing shared_count serialization code to do the majority of the work. Jeff Flinn

Jeff Flinn wrote:
It appears to me that the shared_ptr<T>::px is not even structurally required, but is an optimization trading space to avoid an extra pointer dereference to the sp_counted_base_impl<P,D>::P member. Or have I missed something with my limited exposure?
Consider this example: struct A { int a; }; struct B: public A { int b; }; struct C: public A { int c; }; struct D: public B, public C {}; shared_ptr<D> p1( new D ); shared_ptr<B> p2( p1 ); shared_ptr<C> p3( p1 ); shared_ptr<A> p4( p2 ); shared_ptr<A> p5( p3 ); Now p4 and p5 are both of type shared_ptr<A>, both point to an object with a dynamic type D, but p4.get() != p5.get(). The only difference is in px. (This is an answer to the general shared_ptr question. It's reasonable to disallow serialization in this particular scenario.)
participants (3)
-
Jeff Flinn
-
Peter Dimov
-
Robert Ramey