$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r58258 - in trunk/libs/serialization: src test
From: ramey_at_[hidden]
Date: 2009-12-09 19:30:53
Author: ramey
Date: 2009-12-09 19:30:51 EST (Wed, 09 Dec 2009)
New Revision: 58258
URL: http://svn.boost.org/trac/boost/changeset/58258
Log:
1. Fixed memory leak in shared_ptr loading
2. Fixed error in polymorphic archive implementation
Text files modified: 
   trunk/libs/serialization/src/basic_iarchive.cpp              |    28 +++++++++----                           
   trunk/libs/serialization/src/extended_type_info.cpp          |     7 +++                                     
   trunk/libs/serialization/src/extended_type_info_typeid.cpp   |    10 +++-                                    
   trunk/libs/serialization/src/shared_ptr_helper.cpp           |    32 ++++++++++-----                         
   trunk/libs/serialization/test/Jamfile.v2                     |     1                                         
   trunk/libs/serialization/test/test_shared_ptr.cpp            |    77 +++++++++++++++++++++++---------------- 
   trunk/libs/serialization/test/test_shared_ptr_multi_base.cpp |    53 +++++++++++++++++++++------             
   7 files changed, 141 insertions(+), 67 deletions(-)
Modified: trunk/libs/serialization/src/basic_iarchive.cpp
==============================================================================
--- trunk/libs/serialization/src/basic_iarchive.cpp	(original)
+++ trunk/libs/serialization/src/basic_iarchive.cpp	2009-12-09 19:30:51 EST (Wed, 09 Dec 2009)
@@ -51,7 +51,6 @@
     friend class basic_iarchive;
     version_type m_archive_library_version;
     unsigned int m_flags;
-    const basic_iarchive * m_this;
 
     //////////////////////////////////////////////////////////////////////
     // information about each serialized object loaded
@@ -162,10 +161,9 @@
     const basic_iserializer * pending_bis;
     version_type pending_version;
 
-    basic_iarchive_impl(const basic_iarchive * parent, unsigned int flags) :
+    basic_iarchive_impl(unsigned int flags) :
         m_archive_library_version(BOOST_ARCHIVE_VERSION()),
         m_flags(flags),
-        m_this(parent),
         moveable_objects_start(0),
         moveable_objects_end(0),
         moveable_objects_recent(0),
@@ -214,7 +212,11 @@
     const basic_pointer_iserializer * load_pointer(
         basic_iarchive & ar,
         void * & t, 
-        const basic_pointer_iserializer * bpis
+        const basic_pointer_iserializer * bpis,
+        const basic_pointer_iserializer * (*finder)(
+            const boost::serialization::extended_type_info & type
+        )
+
     );
 };
 
@@ -402,7 +404,11 @@
 basic_iarchive_impl::load_pointer(
     basic_iarchive &ar,
     void * & t,
-    const basic_pointer_iserializer * bpis_ptr
+    const basic_pointer_iserializer * bpis_ptr,
+    const basic_pointer_iserializer * (*finder)(
+        const boost::serialization::extended_type_info & type_
+    )
+
 ){
     class_id_type cid;
     load(ar, cid);
@@ -435,7 +441,7 @@
                 boost::serialization::throw_exception(
                     archive_exception(archive_exception::unregistered_class)
                 );
-            bpis_ptr = m_this->find(*eti);
+            bpis_ptr = (*finder)(*eti);
         }
         assert(NULL != bpis_ptr);
         class_id_type new_cid = register_type(bpis_ptr->get_basic_serializer());
@@ -511,7 +517,7 @@
 
 BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
 basic_iarchive::basic_iarchive(unsigned int flags) : 
-    pimpl(new basic_iarchive_impl(this, flags))
+    pimpl(new basic_iarchive_impl(flags))
 {}
 
 BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
@@ -545,9 +551,13 @@
 BOOST_ARCHIVE_DECL(const basic_pointer_iserializer *)
 basic_iarchive::load_pointer(
     void * &t, 
-    const basic_pointer_iserializer * bpis_ptr
+    const basic_pointer_iserializer * bpis_ptr,
+    const basic_pointer_iserializer * (*finder)(
+        const boost::serialization::extended_type_info & type_
+    )
+
 ){
-    return pimpl->load_pointer(*this, t, bpis_ptr);
+    return pimpl->load_pointer(*this, t, bpis_ptr, finder);
 }
 
 BOOST_ARCHIVE_DECL(void)
Modified: trunk/libs/serialization/src/extended_type_info.cpp
==============================================================================
--- trunk/libs/serialization/src/extended_type_info.cpp	(original)
+++ trunk/libs/serialization/src/extended_type_info.cpp	2009-12-09 19:30:51 EST (Wed, 09 Dec 2009)
@@ -88,6 +88,13 @@
     virtual const char * get_debug_info() const {
         return get_key();
     }
+    virtual void * construct(unsigned int /*count*/, ...) const{
+        assert(false);
+        return NULL;
+    }
+    virtual void destroy(void const * const /*p*/) const {
+        assert(false);
+    }
 public:
     extended_type_info_arg(const char * key) :
         extended_type_info(0, key)
Modified: trunk/libs/serialization/src/extended_type_info_typeid.cpp
==============================================================================
--- trunk/libs/serialization/src/extended_type_info_typeid.cpp	(original)
+++ trunk/libs/serialization/src/extended_type_info_typeid.cpp	2009-12-09 19:30:51 EST (Wed, 09 Dec 2009)
@@ -60,9 +60,6 @@
 extended_type_info_typeid_0::is_equal(
     const boost::serialization::extended_type_info & rhs
 ) const {
-    // shortcut for common case
-    if(this == & rhs)
-        return true;
     return 
         // note: std::type_info == operator returns an int !!!
         // the following permits conversion to bool without a warning.
@@ -122,6 +119,13 @@
 class extended_type_info_typeid_arg : 
     public extended_type_info_typeid_0
 {
+    virtual void * construct(unsigned int /*count*/, ...) const{
+        assert(false);
+        return NULL;
+    }
+    virtual void destroy(void const * const /*p*/) const {
+        assert(false);
+    }
 public:
     extended_type_info_typeid_arg(const std::type_info & ti) :
         extended_type_info_typeid_0(NULL)
Modified: trunk/libs/serialization/src/shared_ptr_helper.cpp
==============================================================================
--- trunk/libs/serialization/src/shared_ptr_helper.cpp	(original)
+++ trunk/libs/serialization/src/shared_ptr_helper.cpp	2009-12-09 19:30:51 EST (Wed, 09 Dec 2009)
@@ -35,18 +35,18 @@
 
 // returns pointer to object and an indicator whether this is a
 // new entry (true) or a previous one (false)
-BOOST_ARCHIVE_DECL(shared_ptr_helper::result_type)
+BOOST_ARCHIVE_DECL(shared_ptr<void>)
 shared_ptr_helper::get_od(
-        void * od,
+        const void * t,
         const boost::serialization::extended_type_info * true_type, 
         const boost::serialization::extended_type_info * this_type
 ){
     // get void pointer to the most derived type
     // this uniquely identifies the object referred to
-    od = void_downcast(
+    const void * od = void_downcast(
         *true_type, 
         *this_type, 
-        od
+        t
     );
     if(NULL == od)
         boost::serialization::throw_exception(
@@ -61,15 +61,21 @@
     if(NULL == m_pointers)
         m_pointers = new collection_type;
 
-    shared_ptr<const void> sp(od, null_deleter()); 
-    std::pair<collection_type::iterator, bool> result =
-        m_pointers->insert(
-            collection_type::value_type(od, sp)
-        );
+    //shared_ptr<const void> sp(od, null_deleter()); 
+    shared_ptr<const void> sp(od, null_deleter());
+    collection_type::iterator i = m_pointers->find(sp);
+
+    if(i == m_pointers->end()){
+        std::pair<collection_type::iterator, bool> result;
+        shared_ptr<const void> sp(const_cast<void * >(od), void_deleter(true_type));
+        result = m_pointers->insert(sp);
+        assert(result.second);
+        i = result.first;
+    }
     od = void_upcast(
         *true_type, 
         *this_type,
-        result.first->first
+        i->get()
     );
     if(NULL == od)
         boost::serialization::throw_exception(
@@ -79,7 +85,11 @@
                 this_type->get_debug_info()
             )
         );
-    return result_type(result.first, od);
+
+    return shared_ptr<void>(
+        const_pointer_cast<void>(*i), 
+        const_cast<void *>(od)
+    );
 }
 
 //  #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
Modified: trunk/libs/serialization/test/Jamfile.v2
==============================================================================
--- trunk/libs/serialization/test/Jamfile.v2	(original)
+++ trunk/libs/serialization/test/Jamfile.v2	2009-12-09 19:30:51 EST (Wed, 09 Dec 2009)
@@ -106,6 +106,7 @@
      [ test-bsl-run_files test_shared_ptr_multi_base ]
      [ test-bsl-run_files test_shared_ptr_132 ]
      [ test-bsl-run_polymorphic_archive test_polymorphic : test_polymorphic_A A ]
+     [ test-bsl-run_polymorphic_archive test_polymorphic2 : test_polymorphic2imp ]
     ;
 
 if ! $(BOOST_ARCHIVE_LIST) {
Modified: trunk/libs/serialization/test/test_shared_ptr.cpp
==============================================================================
--- trunk/libs/serialization/test/test_shared_ptr.cpp	(original)
+++ trunk/libs/serialization/test/test_shared_ptr.cpp	2009-12-09 19:30:51 EST (Wed, 09 Dec 2009)
@@ -38,6 +38,8 @@
     void serialize(Archive & ar, const unsigned int /* file_version */){
         ar & BOOST_SERIALIZATION_NVP(x);
     }
+    A(A const & rhs);
+    A& operator=(A const & rhs);
 public:
     static int count;
     bool operator==(const A & rhs) const {
@@ -250,39 +252,50 @@
 // This does the tests
 int test_main(int /* argc */, char * /* argv */[])
 {
-    // These are our shared_ptrs
-    boost::shared_ptr<A> spa;
-
-    // trivial test 1
-    save_and_load(spa);
+    {
+        boost::shared_ptr<A> spa;
+        // These are our shared_ptrs
+        spa = boost::shared_ptr<A>(new A);
+        boost::shared_ptr<A> spa1 = spa;
+        spa1 = spa;
+    }
+    {
+        // These are our shared_ptrs
+        boost::shared_ptr<A> spa;
 
-    //trivival test 2
-    spa = boost::shared_ptr<A>(new A);
-    save_and_load(spa);
-
-    // Try to save and load pointers to As
-    spa = boost::shared_ptr<A>(new A);
-    boost::shared_ptr<A> spa1 = spa;
-    save_and_load2(spa, spa1);
-
-    // test a weak pointer
-    spa = boost::shared_ptr<A>(new A);
-    spa1 = spa;
-    boost::weak_ptr<A> wp = spa;
-    save_and_load3(spa, spa1, wp);
+        // trivial test 1
+        save_and_load(spa);
     
-    // Try to save and load pointers to Bs
-    spa = boost::shared_ptr<A>(new B);
-    spa1 = spa;
-    save_and_load2(spa, spa1);
-
-    // obj of type B gets destroyed
-    // as smart_ptr goes out of scope
-
-    // Try to save and load pointers to Bs
-    boost::shared_ptr<C> spc;
-    spc = boost::shared_ptr<C>(new C);
-    save_and_load4(spc);
-
+        //trivival test 2
+        spa = boost::shared_ptr<A>(new A);
+        save_and_load(spa);
+
+        // Try to save and load pointers to As
+        spa = boost::shared_ptr<A>(new A);
+        boost::shared_ptr<A> spa1 = spa;
+        save_and_load2(spa, spa1);
+
+        // Try to save and load pointers to Bs
+        spa = boost::shared_ptr<A>(new B);
+        spa1 = spa;
+        save_and_load2(spa, spa1);
+
+        // test a weak pointer
+        spa = boost::shared_ptr<A>(new A);
+        spa1 = spa;
+        boost::weak_ptr<A> wp = spa;
+        save_and_load3(spa, spa1, wp);
+        
+        // obj of type B gets destroyed
+        // as smart_ptr goes out of scope
+    }
+    BOOST_CHECK(A::count == 0);
+    {
+        // Try to save and load pointers to Cs
+        boost::shared_ptr<C> spc;
+        spc = boost::shared_ptr<C>(new C);
+        save_and_load4(spc);
+    }
+    BOOST_CHECK(C::count == 0);
     return EXIT_SUCCESS;
 }
Modified: trunk/libs/serialization/test/test_shared_ptr_multi_base.cpp
==============================================================================
--- trunk/libs/serialization/test/test_shared_ptr_multi_base.cpp	(original)
+++ trunk/libs/serialization/test/test_shared_ptr_multi_base.cpp	2009-12-09 19:30:51 EST (Wed, 09 Dec 2009)
@@ -30,7 +30,8 @@
 struct Base1 {
     Base1() {}
     Base1(int x) : m_x(1 + x) {}
-    virtual ~Base1() {}
+    virtual ~Base1(){
+    }
     int m_x;
     // serialize
     friend class boost::serialization::access;
@@ -41,13 +42,12 @@
     }
 };
 
-BOOST_SERIALIZATION_SHARED_PTR(Base1)
-
 struct Base2 {
     Base2() {}
     Base2(int x) : m_x(2 + x) {}
     int m_x;
-    virtual ~Base2() {}
+    virtual ~Base2(){
+    }
     // serialize
     friend class boost::serialization::access;
     template<class Archive>
@@ -57,12 +57,11 @@
     }
 };
 
-BOOST_SERIALIZATION_SHARED_PTR(Base2)
-
 struct Base3 {
     Base3() {}
     Base3(int x) : m_x(3 + x) {}
-    virtual ~Base3() {}
+    virtual ~Base3(){
+    }
     int m_x;
     // serialize
     friend class boost::serialization::access;
@@ -73,17 +72,28 @@
     }
 };
 
-BOOST_SERIALIZATION_SHARED_PTR(Base3)
-
 // Sub is a subclass of Base1, Base1 and Base3.
 struct Sub:public Base1, public Base2, public Base3 {
-    Sub() {}
+    static int count;
+    Sub() {
+        ++count;
+    }
     Sub(int x) :
         Base1(x),
         Base2(x),
         m_x(x)
-    {}
-    virtual ~Sub() {}
+    {   
+        ++count;
+    }
+    Sub(const Sub & rhs) :
+        m_x(rhs.m_x)
+    {
+        ++count;
+    }
+    virtual ~Sub() {
+        assert(0 < count);
+        --count;
+    }
     int m_x;
     // serialize
     friend class boost::serialization::access;
@@ -101,6 +111,8 @@
 BOOST_CLASS_EXPORT(Sub)
 BOOST_SERIALIZATION_SHARED_PTR(Sub)
 
+int Sub::count = 0;
+
 template <class FIRST, class SECOND>
 void save2(
     const char * testfile, 
@@ -155,6 +167,7 @@
     // Check pointer to vtable
     BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(first));
     BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(second.lock()));
+
     std::remove(testfile);
 }
 
@@ -184,35 +197,45 @@
     // Check pointer to vtable
     BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(first.lock()));
     BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(second));
+
     std::remove(testfile);
 }
 
 // This does the tests
 int test_main(int /* argc */, char * /* argv */[])
 {
+
     // Both Sub
     boost::shared_ptr<Sub> tc1_sp(new Sub(10));
     boost::weak_ptr<Sub> tc1_wp(tc1_sp);
     shared_weak(tc1_sp, tc1_wp);
     weak_shared(tc1_wp, tc1_sp);
+    tc1_sp.reset();
+    BOOST_CHECK(0 == Sub::count);
 
     // Sub and Base1
     boost::shared_ptr<Sub> tc2_sp(new Sub(10));
     boost::weak_ptr<Base1> tc2_wp(tc2_sp);
     shared_weak(tc2_sp, tc2_wp);
     weak_shared(tc2_wp, tc2_sp);
+    tc2_sp.reset();
+    BOOST_CHECK(0 == Sub::count);
 
     // Sub and Base2
     boost::shared_ptr<Sub> tc3_sp(new Sub(10));
     boost::weak_ptr<Base2> tc3_wp(tc3_sp);
     shared_weak(tc3_sp, tc3_wp);
     weak_shared(tc3_wp, tc3_sp);
+    tc3_sp.reset();
+    BOOST_CHECK(0 == Sub::count);
 
     // Sub and Base3
     boost::shared_ptr<Sub> tc4_sp(new Sub(10));
     boost::weak_ptr<Base3> tc4_wp(tc4_sp);
     shared_weak(tc4_sp, tc4_wp);
     weak_shared(tc4_wp, tc4_sp);
+    tc4_sp.reset();
+    BOOST_CHECK(0 == Sub::count);
 
     // Base1 and Base2
     boost::shared_ptr<Sub> tc5_sp_tmp(new Sub(10));
@@ -221,6 +244,8 @@
     tc5_sp_tmp.reset();
     shared_weak(tc5_sp, tc5_wp);
     weak_shared(tc5_wp, tc5_sp);
+    tc5_sp.reset();
+    BOOST_CHECK(0 == Sub::count);
 
     // Base2 and Base3
     boost::shared_ptr<Sub> tc6_sp_tmp(new Sub(10));
@@ -229,6 +254,8 @@
     tc6_sp_tmp.reset();
     shared_weak(tc6_sp, tc6_wp);
     weak_shared(tc6_wp, tc6_sp);
+    tc6_sp.reset();
+    BOOST_CHECK(0 == Sub::count);
 
     // Base3 and Base1
     boost::shared_ptr<Sub> tc7_sp_tmp(new Sub(10));
@@ -237,6 +264,8 @@
     tc7_sp_tmp.reset();
     shared_weak(tc7_sp, tc7_wp);
     weak_shared(tc7_wp, tc7_sp);
+    tc7_sp.reset();
+    BOOST_CHECK(0 == Sub::count);
 
     return EXIT_SUCCESS;
 }