| 1 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
|---|
| 2 | // test_shared_ptr_multi_base.cpp
|
|---|
| 3 |
|
|---|
| 4 | // (C) Copyright 2002 Robert Ramey- http://www.rrsd.com - David Tonge .
|
|---|
| 5 | // (C) Copyright 2009 Takatoshi Kondo.
|
|---|
| 6 | // Use, modification and distribution is subject to the Boost Software
|
|---|
| 7 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
|---|
| 8 | // http://www.boost.org/LICENSE_1_0.txt)
|
|---|
| 9 | //
|
|---|
| 10 | // See http://www.boost.org for updates, documentation, and revision history.
|
|---|
| 11 |
|
|---|
| 12 | #include <cstddef> // NULL
|
|---|
| 13 | #include <cstdio> // remove
|
|---|
| 14 | #include <fstream>
|
|---|
| 15 |
|
|---|
| 16 | #include <boost/config.hpp>
|
|---|
| 17 | #if defined(BOOST_NO_STDC_NAMESPACE)
|
|---|
| 18 | namespace std{
|
|---|
| 19 | using ::remove;
|
|---|
| 20 | }
|
|---|
| 21 | #endif
|
|---|
| 22 | #include <boost/type_traits/broken_compiler_spec.hpp>
|
|---|
| 23 |
|
|---|
| 24 | #include <boost/serialization/shared_ptr.hpp>
|
|---|
| 25 | #include <boost/serialization/weak_ptr.hpp>
|
|---|
| 26 | #include <boost/serialization/nvp.hpp>
|
|---|
| 27 | #include <boost/shared_ptr.hpp>
|
|---|
| 28 | #include <boost/weak_ptr.hpp>
|
|---|
| 29 | #include <boost/serialization/serialization.hpp>
|
|---|
| 30 | #include <boost/archive/xml_oarchive.hpp>
|
|---|
| 31 | #include <boost/archive/xml_iarchive.hpp>
|
|---|
| 32 | #include <boost/serialization/nvp.hpp>
|
|---|
| 33 | #include <boost/serialization/export.hpp>
|
|---|
| 34 | #include <boost/serialization/shared_ptr.hpp>
|
|---|
| 35 | #include <boost/serialization/weak_ptr.hpp>
|
|---|
| 36 |
|
|---|
| 37 | #include "test_tools.hpp"
|
|---|
| 38 |
|
|---|
| 39 | struct Base1 {
|
|---|
| 40 | Base1() {}
|
|---|
| 41 | Base1(int x) : m_x(1 + x) {}
|
|---|
| 42 | virtual ~Base1() {}
|
|---|
| 43 | int m_x;
|
|---|
| 44 | // serialize
|
|---|
| 45 | friend class boost::serialization::access;
|
|---|
| 46 | template<class Archive>
|
|---|
| 47 | void serialize(Archive &ar, const unsigned int /* file_version */)
|
|---|
| 48 | {
|
|---|
| 49 | ar & BOOST_SERIALIZATION_NVP(m_x);
|
|---|
| 50 | }
|
|---|
| 51 | };
|
|---|
| 52 |
|
|---|
| 53 | //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Base1)
|
|---|
| 54 | BOOST_SERIALIZATION_SHARED_PTR(Base1)
|
|---|
| 55 |
|
|---|
| 56 | struct Base2 {
|
|---|
| 57 | Base2() {}
|
|---|
| 58 | Base2(int x) : m_x(2 + x) {}
|
|---|
| 59 | int m_x;
|
|---|
| 60 | virtual ~Base2() {}
|
|---|
| 61 | // serialize
|
|---|
| 62 | friend class boost::serialization::access;
|
|---|
| 63 | template<class Archive>
|
|---|
| 64 | void serialize(Archive &ar, const unsigned int /* file_version */)
|
|---|
| 65 | {
|
|---|
| 66 | ar & BOOST_SERIALIZATION_NVP(m_x);
|
|---|
| 67 | }
|
|---|
| 68 | };
|
|---|
| 69 |
|
|---|
| 70 | //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Base2)
|
|---|
| 71 | BOOST_SERIALIZATION_SHARED_PTR(Base2)
|
|---|
| 72 |
|
|---|
| 73 | struct Base3 {
|
|---|
| 74 | Base3() {}
|
|---|
| 75 | Base3(int x) : m_x(3 + x) {}
|
|---|
| 76 | virtual ~Base3() {}
|
|---|
| 77 | int m_x;
|
|---|
| 78 | // serialize
|
|---|
| 79 | friend class boost::serialization::access;
|
|---|
| 80 | template<class Archive>
|
|---|
| 81 | void serialize(Archive &ar, const unsigned int /* file_version */)
|
|---|
| 82 | {
|
|---|
| 83 | ar & BOOST_SERIALIZATION_NVP(m_x);
|
|---|
| 84 | }
|
|---|
| 85 | };
|
|---|
| 86 |
|
|---|
| 87 | //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Base3)
|
|---|
| 88 | BOOST_SERIALIZATION_SHARED_PTR(Base3)
|
|---|
| 89 |
|
|---|
| 90 | // Sub is a subclass of Base1, Base1 and Base3.
|
|---|
| 91 | struct Sub:public Base1, public Base2, public Base3 {
|
|---|
| 92 | Sub() {}
|
|---|
| 93 | Sub(int x) :
|
|---|
| 94 | Base1(x),
|
|---|
| 95 | Base2(x),
|
|---|
| 96 | m_x(x)
|
|---|
| 97 | {}
|
|---|
| 98 | virtual ~Sub() {}
|
|---|
| 99 | int m_x;
|
|---|
| 100 | // serialize
|
|---|
| 101 | friend class boost::serialization::access;
|
|---|
| 102 | template<class Archive>
|
|---|
| 103 | void serialize(Archive &ar, const unsigned int /* file_version */)
|
|---|
| 104 | {
|
|---|
| 105 | ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base1);
|
|---|
| 106 | ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base2);
|
|---|
| 107 | ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base3);
|
|---|
| 108 | ar & BOOST_SERIALIZATION_NVP(m_x);
|
|---|
| 109 | }
|
|---|
| 110 | };
|
|---|
| 111 |
|
|---|
| 112 | // Sub needs to be exported because its serialized via a base class pointer
|
|---|
| 113 | BOOST_CLASS_EXPORT(Sub)
|
|---|
| 114 | BOOST_SERIALIZATION_SHARED_PTR(Sub)
|
|---|
| 115 |
|
|---|
| 116 | template <class FIRST, class SECOND>
|
|---|
| 117 | void save2(
|
|---|
| 118 | const char * testfile,
|
|---|
| 119 | const FIRST& first,
|
|---|
| 120 | const SECOND& second
|
|---|
| 121 | ){
|
|---|
| 122 | test_ostream os(testfile, TEST_STREAM_FLAGS);
|
|---|
| 123 | test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
|
|---|
| 124 | oa << BOOST_SERIALIZATION_NVP(first);
|
|---|
| 125 | oa << BOOST_SERIALIZATION_NVP(second);
|
|---|
| 126 | }
|
|---|
| 127 |
|
|---|
| 128 | template <class FIRST, class SECOND>
|
|---|
| 129 | void load2(
|
|---|
| 130 | const char * testfile,
|
|---|
| 131 | FIRST& first,
|
|---|
| 132 | SECOND& second)
|
|---|
| 133 | {
|
|---|
| 134 | test_istream is(testfile, TEST_STREAM_FLAGS);
|
|---|
| 135 | test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
|
|---|
| 136 | ia >> BOOST_SERIALIZATION_NVP(first);
|
|---|
| 137 | ia >> BOOST_SERIALIZATION_NVP(second);
|
|---|
| 138 | }
|
|---|
| 139 |
|
|---|
| 140 | // Run tests by serializing two shared_ptrs into an archive,
|
|---|
| 141 | // clearing them (deleting the objects) and then reloading the
|
|---|
| 142 | // objects back from an archive.
|
|---|
| 143 |
|
|---|
| 144 | // Serialization sequence
|
|---|
| 145 | // First, shared_ptr
|
|---|
| 146 | // Second, weak_ptr
|
|---|
| 147 | template <class FIRST, class SECOND>
|
|---|
| 148 | void shared_weak(
|
|---|
| 149 | boost::shared_ptr<FIRST>& first,
|
|---|
| 150 | boost::weak_ptr<SECOND>& second
|
|---|
| 151 | ){
|
|---|
| 152 | const char * testfile = boost::archive::tmpnam(NULL);
|
|---|
| 153 | BOOST_REQUIRE(NULL != testfile);
|
|---|
| 154 | int firstm = first->m_x;
|
|---|
| 155 | int secondm = second.lock()->m_x;
|
|---|
| 156 | save2(testfile, first, second);
|
|---|
| 157 |
|
|---|
| 158 | // Clear the pointers, thereby destroying the objects they contain
|
|---|
| 159 | second.reset();
|
|---|
| 160 | first.reset();
|
|---|
| 161 |
|
|---|
| 162 | load2(testfile, first, second);
|
|---|
| 163 |
|
|---|
| 164 | // Check data member
|
|---|
| 165 | BOOST_CHECK(firstm == first->m_x);
|
|---|
| 166 | BOOST_CHECK(secondm == second.lock()->m_x);
|
|---|
| 167 | // Check pointer to vtable
|
|---|
| 168 | BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(first));
|
|---|
| 169 | BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(second.lock()));
|
|---|
| 170 | std::remove(testfile);
|
|---|
| 171 | }
|
|---|
| 172 |
|
|---|
| 173 | // Serialization sequence
|
|---|
| 174 | // First, weak_ptr
|
|---|
| 175 | // Second, shared_ptr
|
|---|
| 176 | template <class FIRST, class SECOND>
|
|---|
| 177 | void weak_shared(
|
|---|
| 178 | boost::weak_ptr<FIRST>& first,
|
|---|
| 179 | boost::shared_ptr<SECOND>& second
|
|---|
| 180 | ){
|
|---|
| 181 | const char * testfile = boost::archive::tmpnam(NULL);
|
|---|
| 182 | BOOST_REQUIRE(NULL != testfile);
|
|---|
| 183 | int firstm = first.lock()->m_x;
|
|---|
| 184 | int secondm = second->m_x;
|
|---|
| 185 | save2(testfile, first, second);
|
|---|
| 186 |
|
|---|
| 187 | // Clear the pointers, thereby destroying the objects they contain
|
|---|
| 188 | first.reset();
|
|---|
| 189 | second.reset();
|
|---|
| 190 |
|
|---|
| 191 | load2(testfile, first, second);
|
|---|
| 192 |
|
|---|
| 193 | // Check data member
|
|---|
| 194 | BOOST_CHECK(firstm == first.lock()->m_x);
|
|---|
| 195 | BOOST_CHECK(secondm == second->m_x);
|
|---|
| 196 | // Check pointer to vtable
|
|---|
| 197 | BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(first.lock()));
|
|---|
| 198 | BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(second));
|
|---|
| 199 | std::remove(testfile);
|
|---|
| 200 | }
|
|---|
| 201 |
|
|---|
| 202 | // This does the tests
|
|---|
| 203 | int test_main(int /* argc */, char * /* argv */[])
|
|---|
| 204 | {
|
|---|
| 205 | // Both Sub
|
|---|
| 206 | boost::shared_ptr<Sub> tc1_sp(new Sub(10));
|
|---|
| 207 | boost::weak_ptr<Sub> tc1_wp(tc1_sp);
|
|---|
| 208 | shared_weak(tc1_sp, tc1_wp);
|
|---|
| 209 | weak_shared(tc1_wp, tc1_sp);
|
|---|
| 210 |
|
|---|
| 211 | // Sub and Base1
|
|---|
| 212 | boost::shared_ptr<Sub> tc2_sp(new Sub(10));
|
|---|
| 213 | boost::weak_ptr<Base1> tc2_wp(tc2_sp);
|
|---|
| 214 | shared_weak(tc2_sp, tc2_wp);
|
|---|
| 215 | weak_shared(tc2_wp, tc2_sp);
|
|---|
| 216 |
|
|---|
| 217 | // Sub and Base2
|
|---|
| 218 | boost::shared_ptr<Sub> tc3_sp(new Sub(10));
|
|---|
| 219 | boost::weak_ptr<Base2> tc3_wp(tc3_sp);
|
|---|
| 220 | shared_weak(tc3_sp, tc3_wp);
|
|---|
| 221 | weak_shared(tc3_wp, tc3_sp);
|
|---|
| 222 |
|
|---|
| 223 | // Sub and Base3
|
|---|
| 224 | boost::shared_ptr<Sub> tc4_sp(new Sub(10));
|
|---|
| 225 | boost::weak_ptr<Base3> tc4_wp(tc4_sp);
|
|---|
| 226 | shared_weak(tc4_sp, tc4_wp);
|
|---|
| 227 | weak_shared(tc4_wp, tc4_sp);
|
|---|
| 228 |
|
|---|
| 229 | // Base1 and Base2
|
|---|
| 230 | boost::shared_ptr<Sub> tc5_sp_tmp(new Sub(10));
|
|---|
| 231 | boost::shared_ptr<Base1> tc5_sp(tc5_sp_tmp);
|
|---|
| 232 | boost::weak_ptr<Base2> tc5_wp(tc5_sp_tmp);
|
|---|
| 233 | tc5_sp_tmp.reset();
|
|---|
| 234 | shared_weak(tc5_sp, tc5_wp);
|
|---|
| 235 | weak_shared(tc5_wp, tc5_sp);
|
|---|
| 236 |
|
|---|
| 237 | // Base2 and Base3
|
|---|
| 238 | boost::shared_ptr<Sub> tc6_sp_tmp(new Sub(10));
|
|---|
| 239 | boost::shared_ptr<Base2> tc6_sp(tc6_sp_tmp);
|
|---|
| 240 | boost::weak_ptr<Base3> tc6_wp(tc6_sp_tmp);
|
|---|
| 241 | tc6_sp_tmp.reset();
|
|---|
| 242 | shared_weak(tc6_sp, tc6_wp);
|
|---|
| 243 | weak_shared(tc6_wp, tc6_sp);
|
|---|
| 244 |
|
|---|
| 245 | // Base3 and Base1
|
|---|
| 246 | boost::shared_ptr<Sub> tc7_sp_tmp(new Sub(10));
|
|---|
| 247 | boost::shared_ptr<Base3> tc7_sp(tc7_sp_tmp);
|
|---|
| 248 | boost::weak_ptr<Base1> tc7_wp(tc7_sp_tmp);
|
|---|
| 249 | tc7_sp_tmp.reset();
|
|---|
| 250 | shared_weak(tc7_sp, tc7_wp);
|
|---|
| 251 | weak_shared(tc7_wp, tc7_sp);
|
|---|
| 252 |
|
|---|
| 253 | return EXIT_SUCCESS;
|
|---|
| 254 | }
|
|---|