]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/serialization/test/test_enable_shared_from_this.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / serialization / test / test_enable_shared_from_this.cpp
1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // test_enable_shared_from_this.cpp
3
4 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
5 // Use, modification and distribution is subject to the Boost Software
6 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8
9 // This demonstrates a problem with boost::serialization and boost::enable_shared_from_this.
10 // (boost version 1.53)
11 // See boost TRAC ticket #9567
12 //
13 // Given the following class structure:
14 // Base is a simple class
15 // Derived inherits from Base
16 // Derived also inherits from boost::enable_shared_from_this<Derived>
17 // Base and Derived implement boost::serialization
18 //
19 // When deserializing an instance of Derived into a vector of boost::shared_ptr<Derived>:
20 // Base and Derived members are reconstructed correctly.
21 // Derived::shared_from_this() works as expected.
22 //
23 // But when deserializing an instance of Derived into a vector of boost::shared_ptr<Base>:
24 // Base and Derived members are still reconstructed correctly.
25 // Derived::shared_from_this() throws a bad_weak_ptr exception.
26 // This is because enable_shared_from_this::weak_ptr is NOT reconstructed - It is zero.
27
28 #include <sstream>
29
30 #include <boost/archive/text_oarchive.hpp>
31 #include <boost/archive/text_iarchive.hpp>
32
33 #include <boost/enable_shared_from_this.hpp>
34 #include <boost/serialization/shared_ptr.hpp>
35 #include <boost/serialization/export.hpp>
36 #include <boost/serialization/split_free.hpp>
37
38 #include "test_tools.hpp"
39
40 #include <set>
41
42 namespace boost {
43 namespace serialization {
44
45 struct enable_shared_from_this_helper {
46 std::set<shared_ptr<void> > m_esfth;
47 void record(boost::shared_ptr<void> sp){
48 m_esfth.insert(sp);
49 }
50 };
51
52 template<class Archive, class T>
53 void serialize(
54 Archive & ar,
55 boost::enable_shared_from_this<T> & t,
56 const unsigned int file_version
57 ){
58 enable_shared_from_this_helper & h =
59 ar.template get_helper<
60 enable_shared_from_this_helper
61 >();
62
63 shared_ptr<T> sp = t.shared_from_this();
64 h.record(sp);
65 }
66
67 } // serialization
68 } // boost
69
70 class Base {
71 friend class boost::serialization::access;
72
73 template<class Archive>
74 void serialize(Archive & ar, const unsigned int version)
75 {
76 ar & BOOST_SERIALIZATION_NVP(m_base);
77 }
78 protected:
79 Base() {}
80 virtual ~Base() {} // "virtual" forces RTTI, to enable serialization of Derived from Base pointer
81 public:
82 int m_base;
83 };
84
85 class Derived : public Base, public boost::enable_shared_from_this<Derived> {
86 friend class boost::serialization::access;
87
88 template<class Archive>
89 void serialize(Archive & ar, const unsigned int version)
90 {
91 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
92 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(
93 boost::enable_shared_from_this<Derived>
94 );
95 ar & BOOST_SERIALIZATION_NVP(m_derived);
96 }
97 public:
98 boost::shared_ptr<Derived> SharedPtr() { return shared_from_this(); }
99 int m_derived;
100 Derived() {}
101 ~Derived() {}
102 };
103 // The following is required to enable serialization from Base pointer
104 BOOST_CLASS_EXPORT(Derived)
105
106 // This test passes
107 void test_passes(){
108 std::stringstream ss;
109 {
110 boost::shared_ptr<Derived> d(new Derived());
111 d->m_base = 1;
112 d->m_derived = 2;
113
114 // Get a raw pointer to Derived
115 Derived* raw_d = d.get();
116
117 // Verify base and derived members
118 BOOST_CHECK(raw_d->m_base==1);
119 BOOST_CHECK(raw_d->m_derived==2);
120
121 // verify shared_from_this
122 BOOST_CHECK(d == raw_d->SharedPtr());
123
124 boost::archive::text_oarchive oa(ss);
125 oa & BOOST_SERIALIZATION_NVP(d);
126 }
127 {
128 // Deserialize it back into a vector of shared_ptr<Derived>
129 boost::shared_ptr<Derived> d;
130 ss.seekg(0);
131 boost::archive::text_iarchive ia(ss);
132 ia & BOOST_SERIALIZATION_NVP(d);
133
134 // Get a raw pointer to Derived
135 Derived* raw_d = d.get();
136
137 // Verify base and derived members
138 BOOST_CHECK(raw_d->m_base==1);
139 BOOST_CHECK(raw_d->m_derived==2);
140
141 // verify shared_from_this
142 BOOST_CHECK(d == raw_d->SharedPtr());
143 }
144 }
145
146 // This test fails
147 void test_fails(){
148 std::stringstream ss;
149 {
150 boost::shared_ptr<Base> b(new Derived());
151 Derived* raw_d1 = static_cast<Derived*>(b.get());
152 raw_d1->m_base = 1;
153 raw_d1->m_derived = 2;
154
155 // Get a raw pointer to Derived via shared_ptr<Base>
156 Derived* raw_d = static_cast<Derived*>(b.get());
157
158 // Verify base and derived members
159 BOOST_CHECK(raw_d->m_base==1);
160 BOOST_CHECK(raw_d->m_derived==2);
161
162 // verify shared_from_this
163 boost::shared_ptr<Derived> d = raw_d->SharedPtr();
164 BOOST_CHECK(d == b);
165 // Serialize the vector
166 boost::archive::text_oarchive oa(ss);
167 oa & BOOST_SERIALIZATION_NVP(b);
168 }
169 {
170 // Deserialize it back into a vector of shared_ptr<Base>
171 ss.seekg(0);
172 boost::archive::text_iarchive ia(ss);
173 boost::shared_ptr<Base> b;
174 ia & BOOST_SERIALIZATION_NVP(b);
175
176 // Get a raw pointer to Derived via shared_ptr<Base>
177 Derived* raw_d = static_cast<Derived*>(b.get());
178 // Verify base and derived members
179 BOOST_CHECK(raw_d->m_base==1);
180 BOOST_CHECK(raw_d->m_derived==2);
181
182 // verify shared_from_this
183 // FAIL: The following line throws bad_weak_ptr exception
184 boost::shared_ptr<Derived> d = raw_d->SharedPtr();
185 BOOST_CHECK(d == b);
186 }
187 }
188
189 int test_main(int /*argc*/, char * /*argv */[]){
190 test_fails();
191 test_passes();
192 return EXIT_SUCCESS;
193 }
194
195 // EOF