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 | }
|
---|