diff options
Diffstat (limited to '')
-rw-r--r-- | src/boost/libs/serialization/test/test_enable_shared_from_this.cpp | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/boost/libs/serialization/test/test_enable_shared_from_this.cpp b/src/boost/libs/serialization/test/test_enable_shared_from_this.cpp new file mode 100644 index 000000000..608837e22 --- /dev/null +++ b/src/boost/libs/serialization/test/test_enable_shared_from_this.cpp @@ -0,0 +1,195 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// test_enable_shared_from_this.cpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// This demonstrates a problem with boost::serialization and boost::enable_shared_from_this. +// (boost version 1.53) +// See boost TRAC ticket #9567 +// +// Given the following class structure: +// Base is a simple class +// Derived inherits from Base +// Derived also inherits from boost::enable_shared_from_this<Derived> +// Base and Derived implement boost::serialization +// +// When deserializing an instance of Derived into a vector of boost::shared_ptr<Derived>: +// Base and Derived members are reconstructed correctly. +// Derived::shared_from_this() works as expected. +// +// But when deserializing an instance of Derived into a vector of boost::shared_ptr<Base>: +// Base and Derived members are still reconstructed correctly. +// Derived::shared_from_this() throws a bad_weak_ptr exception. +// This is because enable_shared_from_this::weak_ptr is NOT reconstructed - It is zero. + +#include <sstream> + +#include <boost/archive/text_oarchive.hpp> +#include <boost/archive/text_iarchive.hpp> + +#include <boost/enable_shared_from_this.hpp> +#include <boost/serialization/shared_ptr.hpp> +#include <boost/serialization/export.hpp> +#include <boost/serialization/split_free.hpp> + +#include "test_tools.hpp" + +#include <set> + +namespace boost { +namespace serialization { + +struct enable_shared_from_this_helper { + std::set<shared_ptr<void> > m_esfth; + void record(boost::shared_ptr<void> sp){ + m_esfth.insert(sp); + } +}; + +template<class Archive, class T> +void serialize( + Archive & ar, + boost::enable_shared_from_this<T> & t, + const unsigned int file_version +){ + enable_shared_from_this_helper & h = + ar.template get_helper< + enable_shared_from_this_helper + >(); + + shared_ptr<T> sp = t.shared_from_this(); + h.record(sp); +} + +} // serialization +} // boost + +class Base { + friend class boost::serialization::access; + + template<class Archive> + void serialize(Archive & ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_NVP(m_base); + } +protected: + Base() {} + virtual ~Base() {} // "virtual" forces RTTI, to enable serialization of Derived from Base pointer +public: + int m_base; +}; + +class Derived : public Base, public boost::enable_shared_from_this<Derived> { + friend class boost::serialization::access; + + template<class Archive> + void serialize(Archive & ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( + boost::enable_shared_from_this<Derived> + ); + ar & BOOST_SERIALIZATION_NVP(m_derived); + } +public: + boost::shared_ptr<Derived> SharedPtr() { return shared_from_this(); } + int m_derived; + Derived() {} + ~Derived() {} +}; +// The following is required to enable serialization from Base pointer +BOOST_CLASS_EXPORT(Derived) + +// This test passes +void test_passes(){ + std::stringstream ss; + { + boost::shared_ptr<Derived> d(new Derived()); + d->m_base = 1; + d->m_derived = 2; + + // Get a raw pointer to Derived + Derived* raw_d = d.get(); + + // Verify base and derived members + BOOST_CHECK(raw_d->m_base==1); + BOOST_CHECK(raw_d->m_derived==2); + + // verify shared_from_this + BOOST_CHECK(d == raw_d->SharedPtr()); + + boost::archive::text_oarchive oa(ss); + oa & BOOST_SERIALIZATION_NVP(d); + } + { + // Deserialize it back into a vector of shared_ptr<Derived> + boost::shared_ptr<Derived> d; + ss.seekg(0); + boost::archive::text_iarchive ia(ss); + ia & BOOST_SERIALIZATION_NVP(d); + + // Get a raw pointer to Derived + Derived* raw_d = d.get(); + + // Verify base and derived members + BOOST_CHECK(raw_d->m_base==1); + BOOST_CHECK(raw_d->m_derived==2); + + // verify shared_from_this + BOOST_CHECK(d == raw_d->SharedPtr()); + } +} + +// This test fails +void test_fails(){ + std::stringstream ss; + { + boost::shared_ptr<Base> b(new Derived()); + Derived* raw_d1 = static_cast<Derived*>(b.get()); + raw_d1->m_base = 1; + raw_d1->m_derived = 2; + + // Get a raw pointer to Derived via shared_ptr<Base> + Derived* raw_d = static_cast<Derived*>(b.get()); + + // Verify base and derived members + BOOST_CHECK(raw_d->m_base==1); + BOOST_CHECK(raw_d->m_derived==2); + + // verify shared_from_this + boost::shared_ptr<Derived> d = raw_d->SharedPtr(); + BOOST_CHECK(d == b); + // Serialize the vector + boost::archive::text_oarchive oa(ss); + oa & BOOST_SERIALIZATION_NVP(b); + } + { + // Deserialize it back into a vector of shared_ptr<Base> + ss.seekg(0); + boost::archive::text_iarchive ia(ss); + boost::shared_ptr<Base> b; + ia & BOOST_SERIALIZATION_NVP(b); + + // Get a raw pointer to Derived via shared_ptr<Base> + Derived* raw_d = static_cast<Derived*>(b.get()); + // Verify base and derived members + BOOST_CHECK(raw_d->m_base==1); + BOOST_CHECK(raw_d->m_derived==2); + + // verify shared_from_this + // FAIL: The following line throws bad_weak_ptr exception + boost::shared_ptr<Derived> d = raw_d->SharedPtr(); + BOOST_CHECK(d == b); + } +} + +int test_main(int /*argc*/, char * /*argv */[]){ + test_fails(); + test_passes(); + return EXIT_SUCCESS; +} + +// EOF |