From c6e3c3fe52da6819cc16d385c70ae03edbef0b32 Mon Sep 17 00:00:00 2001 From: Brandon Kohn Date: Wed, 22 Jan 2014 15:52:19 -0500 Subject: [PATCH] Added new method for loading tracked pointers which updates cached ptrs before deserializing. --- .../archive/detail/basic_pointer_iserializer.hpp | 7 +++ include/boost/archive/detail/iserializer.hpp | 58 +++++++++++++++++++++- src/basic_iarchive.cpp | 3 +- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/include/boost/archive/detail/basic_pointer_iserializer.hpp b/include/boost/archive/detail/basic_pointer_iserializer.hpp index 5decea2..bd4ff40 100644 --- a/include/boost/archive/detail/basic_pointer_iserializer.hpp +++ b/include/boost/archive/detail/basic_pointer_iserializer.hpp @@ -58,6 +58,13 @@ public: void * & x, const unsigned int file_version ) const = 0; + + virtual void load_object_ptr_tracked( + basic_iarchive & ar, + void * & x, + void * & tx, + const unsigned int file_version + ) const = 0; }; } // namespace detail diff --git a/include/boost/archive/detail/iserializer.hpp b/include/boost/archive/detail/iserializer.hpp index 62aac9d..21e52bc 100644 --- a/include/boost/archive/detail/iserializer.hpp +++ b/include/boost/archive/detail/iserializer.hpp @@ -206,11 +206,18 @@ private: iserializer >::get_const_instance(); } - BOOST_DLLEXPORT virtual void load_object_ptr( + BOOST_DLLEXPORT virtual void load_object_ptr( basic_iarchive & ar, void * & x, const unsigned int file_version ) const BOOST_USED; + + BOOST_DLLEXPORT virtual void load_object_ptr_tracked( + basic_iarchive & ar, + void * & x, + void * & tx, + const unsigned int file_version + ) const BOOST_USED; protected: // this should alway be a singleton so make the constructor protected pointer_iserializer(); @@ -428,6 +435,55 @@ BOOST_DLLEXPORT void pointer_iserializer::load_object_ptr( h.release(); } +// note: BOOST_DLLEXPORT is so that code for polymorphic class +// serialized only through base class won't get optimized out +template +BOOST_DLLEXPORT void pointer_iserializer::load_object_ptr_tracked( + basic_iarchive & ar, + void * & t, + void * & tx, + const unsigned int file_version +) const +{ + Archive & ar_impl = + boost::serialization::smart_cast_reference(ar); + + heap_allocation h; + t = NULL; + // note that the above will throw std::bad_alloc if the allocation + // fails so we don't have to address this contingency here. + + // catch exception during load_construct_data so that we don't + // automatically delete the t which is most likely not fully + // constructed + BOOST_TRY { + // this addresses an obscure situation that occurs when + // load_constructor de-serializes something through a pointer. + ar.next_object_pointer(h.get()); + boost::serialization::load_construct_data_adl( + ar_impl, + h.get(), + file_version + ); + + //! Update the value of the stored pointer so cycles can use it. + tx = h.get();//Assign to the tracker the newly constructed value. + } + BOOST_CATCH(...){ + // if we get here the load_construct failed. The heap_allocation + // will be automatically deleted so we don't have to do anything + // special here. + BOOST_RETHROW; + } + BOOST_CATCH_END + + ar_impl >> boost::serialization::make_nvp(NULL, *h.get()); + // success !!! - release the heap allocation so it + // doesn't delete the object we just loaded. + t = h.get(); + h.release(); +} + template pointer_iserializer::pointer_iserializer() : basic_pointer_iserializer( diff --git a/src/basic_iarchive.cpp b/src/basic_iarchive.cpp index 6be5d9d..a066514 100644 --- a/src/basic_iarchive.cpp +++ b/src/basic_iarchive.cpp @@ -518,9 +518,10 @@ basic_iarchive_impl::load_pointer( // remember that that the address of these elements could change // when we make another call so don't use the address - bpis_ptr->load_object_ptr( + bpis_ptr->load_object_ptr_tracked( ar, t, + object_id_vector[ui].address, m_pending.version ); BOOST_ASSERT(NULL != t); -- 1.8.0.msysgit.0