]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/serialization/example/demo_exception.cpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / libs / serialization / example / demo_exception.cpp
1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // demo_exception.cpp
3
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)
8
9 // Example of safe exception handling for pointer de-serialization
10 //
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.
14 //
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.
19
20 #include <algorithm>
21 #include <iostream>
22 #include <cstddef> // NULL
23 #include <fstream>
24 #include <string>
25
26 #include <cstdio> // remove
27 #include <boost/config.hpp>
28 #if defined(BOOST_NO_STDC_NAMESPACE)
29 namespace std{
30 using ::remove;
31 }
32 #endif
33
34 #include <boost/archive/tmpdir.hpp>
35
36 #ifndef BOOST_NO_EXCEPTIONS
37 #include <exception>
38 #endif
39
40 #include <boost/archive/text_iarchive.hpp>
41 #include <boost/archive/text_oarchive.hpp>
42
43 #include <boost/serialization/list.hpp>
44 #include <boost/serialization/split_member.hpp>
45
46 template<class TPTR>
47 struct deleter
48 {
49 void operator()(TPTR t){
50 delete t;
51 }
52 };
53
54 class Course;
55 class Student;
56
57 class Student
58 {
59 public:
60 static int count;
61 Student(){
62 count++;
63 }
64 ~Student(){
65 some_courses.clear();
66 count--;
67 }
68 std::list<Course *> some_courses;
69 private:
70 friend class boost::serialization::access;
71 template<class Archive>
72 void serialize(Archive & ar, const unsigned int /* file_version */){
73 ar & some_courses;
74 }
75 };
76
77 int Student::count = 0;
78
79 class Course
80 {
81 public:
82 static int count;
83 Course(){
84 count++;
85 }
86 ~Course(){
87 // doesnt delete pointers in list
88 // since it doesn't "own" them
89 some_students.clear();
90 count--;
91 }
92 std::list<Student *> some_students;
93 private:
94 friend class boost::serialization::access;
95 template<class Archive>
96 void serialize(Archive & ar, const unsigned int /* file_version */){
97 ar & some_students;
98 }
99 };
100
101 int Course::count = 0;
102
103 class School
104 {
105 public:
106 ~School(){
107 // must delete all the students because
108 // it "owns" them
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 *>());
113 all_courses.clear();
114 }
115 std::list<Student *> all_students;
116 std::list<Course *> all_courses;
117 private:
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);
124 };
125
126 #if 0
127 // case 1:
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
132 // with students
133 ar & all_courses;
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.
139 }
140
141 // switching the order of serialization doesn't help in this case
142 // case 2:
143 template<class Archive>
144 void School::serialize(Archive & ar, const unsigned int /* file_version */){
145 ar & all_students;
146 ar >> all_courses; // create any courses that have no students
147 }
148 #endif
149
150 template<class Archive>
151 void School::save(Archive & ar, const unsigned int /* file_version */) const {
152 ar << all_students;
153 ar << all_courses;
154 }
155
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
160 // with students
161 try{
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.
166 ar >> all_courses;
167 ar >> all_students; // create students that have no courses
168 }
169 catch(std::exception){
170 // elminate any dangling references
171 all_courses.clear();
172 all_students.clear();
173 throw;
174 }
175 }
176
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();
182
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);
187
188 Course *math = new Course();
189 Course *history = new Course();
190 Course *literature = new Course();
191 Course *gym = new Course();
192
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);
197
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);
202
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);
207
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);
212
213 // no students signed up for gym
214 // carol has no courses
215 }
216
217 void save(const School * const school, const char *filename){
218 std::ofstream ofile(filename);
219 boost::archive::text_oarchive ar(ofile);
220 ar << school;
221 }
222
223 void load(School * & school, const char *filename){
224 std::ifstream ifile(filename);
225 boost::archive::text_iarchive ar(ifile);
226 try{
227 ar >> school;
228 }
229 catch(std::exception){
230 // eliminate dangling reference
231 school = NULL;
232 }
233 }
234
235 int main(int argc, char *argv[]){
236 std::string filename(boost::archive::tmpdir());
237 filename += "/demofile.txt";
238
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;
242 init(school);
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());
246 delete school;
247 school = NULL;
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;
253 delete school;
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;
258 }