123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- /////////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
|