diff --git a/src/basic_iarchive.cpp b/src/basic_iarchive.cpp index 3b8ab64e..861868f8 100644 --- a/src/basic_iarchive.cpp +++ b/src/basic_iarchive.cpp @@ -51,7 +51,6 @@ class basic_iarchive_impl { 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 @@ class basic_iarchive_impl { 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 @@ class basic_iarchive_impl { 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 @@ inline const basic_pointer_iserializer * 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 @@ basic_iarchive_impl::load_pointer( 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 @@ basic_iarchive::next_object_pointer(void *t){ 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 @@ basic_iarchive::load_object( 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) diff --git a/src/extended_type_info.cpp b/src/extended_type_info.cpp index d05fa7e3..bc28d6ad 100644 --- a/src/extended_type_info.cpp +++ b/src/extended_type_info.cpp @@ -88,6 +88,13 @@ class extended_type_info_arg : public extended_type_info 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) diff --git a/src/extended_type_info_typeid.cpp b/src/extended_type_info_typeid.cpp index 11557371..8b5e38d6 100644 --- a/src/extended_type_info_typeid.cpp +++ b/src/extended_type_info_typeid.cpp @@ -60,9 +60,6 @@ BOOST_SERIALIZATION_DECL(bool) 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 @@ extended_type_info_typeid_0::type_unregister() 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) diff --git a/src/shared_ptr_helper.cpp b/src/shared_ptr_helper.cpp index 0918876f..995010ad 100644 --- a/src/shared_ptr_helper.cpp +++ b/src/shared_ptr_helper.cpp @@ -35,18 +35,18 @@ namespace detail { // 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) 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 @@ shared_ptr_helper::get_od( if(NULL == m_pointers) m_pointers = new collection_type; - shared_ptr sp(od, null_deleter()); - std::pair result = - m_pointers->insert( - collection_type::value_type(od, sp) - ); + //shared_ptr sp(od, null_deleter()); + shared_ptr sp(od, null_deleter()); + collection_type::iterator i = m_pointers->find(sp); + + if(i == m_pointers->end()){ + std::pair result; + shared_ptr sp(const_cast(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 @@ shared_ptr_helper::get_od( this_type->get_debug_info() ) ); - return result_type(result.first, od); + + return shared_ptr( + const_pointer_cast(*i), + const_cast(od) + ); } // #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 26301d59..03646401 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -106,6 +106,7 @@ test-suite "serialization" : [ 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) { diff --git a/test/test_shared_ptr.cpp b/test/test_shared_ptr.cpp index 42e016c3..6d7a1025 100644 --- a/test/test_shared_ptr.cpp +++ b/test/test_shared_ptr.cpp @@ -38,6 +38,8 @@ private: 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 @@ void save_and_load4(boost::shared_ptr& spc) // This does the tests int test_main(int /* argc */, char * /* argv */[]) { - // These are our shared_ptrs - boost::shared_ptr spa; + { + boost::shared_ptr spa; + // These are our shared_ptrs + spa = boost::shared_ptr(new A); + boost::shared_ptr spa1 = spa; + spa1 = spa; + } + { + // These are our shared_ptrs + boost::shared_ptr spa; - // trivial test 1 - save_and_load(spa); - - //trivival test 2 - spa = boost::shared_ptr(new A); - save_and_load(spa); - - // Try to save and load pointers to As - spa = boost::shared_ptr(new A); - boost::shared_ptr spa1 = spa; - save_and_load2(spa, spa1); - - // test a weak pointer - spa = boost::shared_ptr(new A); - spa1 = spa; - boost::weak_ptr 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(new B); - spa1 = spa; - save_and_load2(spa, spa1); + //trivival test 2 + spa = boost::shared_ptr(new A); + save_and_load(spa); - // obj of type B gets destroyed - // as smart_ptr goes out of scope + // Try to save and load pointers to As + spa = boost::shared_ptr(new A); + boost::shared_ptr spa1 = spa; + save_and_load2(spa, spa1); - // Try to save and load pointers to Bs - boost::shared_ptr spc; - spc = boost::shared_ptr(new C); - save_and_load4(spc); + // Try to save and load pointers to Bs + spa = boost::shared_ptr(new B); + spa1 = spa; + save_and_load2(spa, spa1); + // test a weak pointer + spa = boost::shared_ptr(new A); + spa1 = spa; + boost::weak_ptr 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 spc; + spc = boost::shared_ptr(new C); + save_and_load4(spc); + } + BOOST_CHECK(C::count == 0); return EXIT_SUCCESS; } diff --git a/test/test_shared_ptr_multi_base.cpp b/test/test_shared_ptr_multi_base.cpp index aebfcb75..21dbd628 100644 --- a/test/test_shared_ptr_multi_base.cpp +++ b/test/test_shared_ptr_multi_base.cpp @@ -30,7 +30,8 @@ namespace std{ 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 @@ struct Base1 { } }; -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 @@ -57,12 +57,11 @@ struct Base2 { } }; -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 @@ struct Base3 { } }; -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 @@ struct Sub:public Base1, public Base2, public Base3 { BOOST_CLASS_EXPORT(Sub) BOOST_SERIALIZATION_SHARED_PTR(Sub) +int Sub::count = 0; + template void save2( const char * testfile, @@ -155,6 +167,7 @@ void shared_weak( // Check pointer to vtable BOOST_CHECK(boost::dynamic_pointer_cast(first)); BOOST_CHECK(boost::dynamic_pointer_cast(second.lock())); + std::remove(testfile); } @@ -184,35 +197,45 @@ void weak_shared( // Check pointer to vtable BOOST_CHECK(boost::dynamic_pointer_cast(first.lock())); BOOST_CHECK(boost::dynamic_pointer_cast(second)); + std::remove(testfile); } // This does the tests int test_main(int /* argc */, char * /* argv */[]) { + // Both Sub boost::shared_ptr tc1_sp(new Sub(10)); boost::weak_ptr 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 tc2_sp(new Sub(10)); boost::weak_ptr 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 tc3_sp(new Sub(10)); boost::weak_ptr 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 tc4_sp(new Sub(10)); boost::weak_ptr 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 tc5_sp_tmp(new Sub(10)); @@ -221,6 +244,8 @@ int test_main(int /* argc */, char * /* argv */[]) 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 tc6_sp_tmp(new Sub(10)); @@ -229,6 +254,8 @@ int test_main(int /* argc */, char * /* argv */[]) 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 tc7_sp_tmp(new Sub(10)); @@ -237,6 +264,8 @@ int test_main(int /* argc */, char * /* argv */[]) 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; }