Boost logo

Boost :

From: Jeff Flinn (TriumphSprint2000_at_[hidden])
Date: 2004-05-19 13:49:47


"Robert Ramey" <ramey_at_[hidden]> wrote in message
news:20040519164342.3E2E03150B_at_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


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