]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/serialization/example/demo_exception.cpp
1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
4 // (C) Copyright 2002-4 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)
9 // Example of safe exception handling for pointer de-serialization
11 // This example was prepared by Robert Ramey to demonstrate and test
12 // safe exception handling during the de-serialization of pointers in
13 // a non-trivial example.
15 // Hopefully, this addresses exception issues raised by
16 // Vahan Margaryan who spent considerable time and effort
17 // in the analysis and testing of issues of exception safety
18 // of the serialization library.
22 #include <cstddef> // NULL
26 #include <cstdio> // remove
27 #include <boost/config.hpp>
28 #if defined(BOOST_NO_STDC_NAMESPACE)
34 #include <boost/archive/tmpdir.hpp>
36 #ifndef BOOST_NO_EXCEPTIONS
40 #include <boost/archive/text_iarchive.hpp>
41 #include <boost/archive/text_oarchive.hpp>
43 #include <boost/serialization/list.hpp>
44 #include <boost/serialization/split_member.hpp>
49 void operator()(TPTR t
){
68 std::list
<Course
*> some_courses
;
70 friend class boost::serialization::access
;
71 template<class Archive
>
72 void serialize(Archive
& ar
, const unsigned int /* file_version */){
77 int Student::count
= 0;
87 // doesnt delete pointers in list
88 // since it doesn't "own" them
89 some_students
.clear();
92 std::list
<Student
*> some_students
;
94 friend class boost::serialization::access
;
95 template<class Archive
>
96 void serialize(Archive
& ar
, const unsigned int /* file_version */){
101 int Course::count
= 0;
107 // must delete all the students because
109 std::for_each(all_students
.begin(), all_students
.end(), deleter
<Student
*>());
110 all_students
.clear();
111 // as well as courses
112 std::for_each(all_courses
.begin(), all_courses
.end(), deleter
<Course
*>());
115 std::list
<Student
*> all_students
;
116 std::list
<Course
*> all_courses
;
118 friend class boost::serialization::access
;
119 BOOST_SERIALIZATION_SPLIT_MEMBER()
120 template<class Archive
>
121 void save(Archive
& ar
, const unsigned int file_version
) const;
122 template<class Archive
>
123 void load(Archive
& ar
, const unsigned int file_version
);
128 template<class Archive
>
129 void School::serialize(Archive
& ar
, const unsigned int /* file_version */){
130 // if an exeception occurs while loading courses
131 // the structure courses may have some courses each
134 // while all_students will have no members.
135 ar
& all_students
; // create students that have no courses
136 // so ~School() will delete all members of courses
137 // but this will NOT delete any students - see above
138 // a memory leak will be the result.
141 // switching the order of serialization doesn't help in this case
143 template<class Archive
>
144 void School::serialize(Archive
& ar
, const unsigned int /* file_version */){
146 ar
>> all_courses
; // create any courses that have no students
150 template<class Archive
>
151 void School::save(Archive
& ar
, const unsigned int /* file_version */) const {
156 template<class Archive
>
157 void School::load(Archive
& ar
, const unsigned int /* file_version */){
158 // if an exeception occurs while loading courses
159 // the structure courses may have some courses each
162 // deserialization of a Course * will in general provoke the
163 // deserialization of Student * which are added to the list of
164 // students for a class. That is, this process will result
165 // in the copying of a pointer.
167 ar
>> all_students
; // create students that have no courses
169 catch(std::exception
){
170 // elminate any dangling references
172 all_students
.clear();
177 void init(School
*school
){
178 Student
*bob
= new Student();
179 Student
*ted
= new Student();
180 Student
*carol
= new Student();
181 Student
*alice
= new Student();
183 school
->all_students
.push_back(bob
);
184 school
->all_students
.push_back(ted
);
185 school
->all_students
.push_back(carol
);
186 school
->all_students
.push_back(alice
);
188 Course
*math
= new Course();
189 Course
*history
= new Course();
190 Course
*literature
= new Course();
191 Course
*gym
= new Course();
193 school
->all_courses
.push_back(math
);
194 school
->all_courses
.push_back(history
);
195 school
->all_courses
.push_back(literature
);
196 school
->all_courses
.push_back(gym
);
198 bob
->some_courses
.push_back(math
);
199 math
->some_students
.push_back(bob
);
200 bob
->some_courses
.push_back(literature
);
201 literature
->some_students
.push_back(bob
);
203 ted
->some_courses
.push_back(math
);
204 math
->some_students
.push_back(ted
);
205 ted
->some_courses
.push_back(history
);
206 history
->some_students
.push_back(ted
);
208 alice
->some_courses
.push_back(literature
);
209 literature
->some_students
.push_back(alice
);
210 alice
->some_courses
.push_back(history
);
211 history
->some_students
.push_back(alice
);
213 // no students signed up for gym
214 // carol has no courses
217 void save(const School
* const school
, const char *filename
){
218 std::ofstream
ofile(filename
);
219 boost::archive::text_oarchive
ar(ofile
);
223 void load(School
* & school
, const char *filename
){
224 std::ifstream
ifile(filename
);
225 boost::archive::text_iarchive
ar(ifile
);
229 catch(std::exception
){
230 // eliminate dangling reference
235 int main(int argc
, char *argv
[]){
236 std::string
filename(boost::archive::tmpdir());
237 filename
+= "/demofile.txt";
239 School
*school
= new School();
240 std::cout
<< "1. student count = " << Student::count
<< std::endl
;
241 std::cout
<< "2. class count = " << Course::count
<< std::endl
;
243 std::cout
<< "3. student count = " << Student::count
<< std::endl
;
244 std::cout
<< "4. class count = " << Course::count
<< std::endl
;
245 save(school
, filename
.c_str());
248 std::cout
<< "5. student count = " << Student::count
<< std::endl
;
249 std::cout
<< "6. class count = " << Course::count
<< std::endl
;
250 load(school
, filename
.c_str());
251 std::cout
<< "7. student count = " << Student::count
<< std::endl
;
252 std::cout
<< "8. class count = " << Course::count
<< std::endl
;
254 std::cout
<< "9. student count = " << Student::count
<< std::endl
;
255 std::cout
<< "10. class count = " << Course::count
<< std::endl
;
256 std::remove(filename
.c_str());
257 return Student::count
+ Course::count
;