Chris@102
|
1 #ifndef BOOST_SERIALIZATION_SHARED_PTR_HELPER_HPP
|
Chris@102
|
2 #define BOOST_SERIALIZATION_SHARED_PTR_HELPER_HPP
|
Chris@102
|
3
|
Chris@102
|
4 // MS compatible compilers support #pragma once
|
Chris@102
|
5 #if defined(_MSC_VER)
|
Chris@102
|
6 # pragma once
|
Chris@102
|
7 #endif
|
Chris@102
|
8
|
Chris@102
|
9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
Chris@102
|
10 // shared_ptr_helper.hpp: serialization for boost shared pointern
|
Chris@102
|
11
|
Chris@102
|
12 // (C) Copyright 2004-2009 Robert Ramey, Martin Ecker and Takatoshi Kondo
|
Chris@102
|
13 // Use, modification and distribution is subject to the Boost Software
|
Chris@102
|
14 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@102
|
15 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
16
|
Chris@102
|
17 // See http://www.boost.org for updates, documentation, and revision history.
|
Chris@102
|
18
|
Chris@102
|
19 #include <map>
|
Chris@102
|
20 #include <list>
|
Chris@102
|
21 #include <utility>
|
Chris@102
|
22 #include <cstddef> // NULL
|
Chris@102
|
23
|
Chris@102
|
24 #include <boost/config.hpp>
|
Chris@102
|
25 #include <boost/shared_ptr.hpp>
|
Chris@102
|
26 #include <boost/type_traits/is_polymorphic.hpp>
|
Chris@102
|
27 #include <boost/mpl/if.hpp>
|
Chris@102
|
28
|
Chris@102
|
29 #include <boost/serialization/singleton.hpp>
|
Chris@102
|
30 #include <boost/serialization/extended_type_info.hpp>
|
Chris@102
|
31 #include <boost/serialization/throw_exception.hpp>
|
Chris@102
|
32 #include <boost/serialization/type_info_implementation.hpp>
|
Chris@102
|
33 #include <boost/archive/archive_exception.hpp>
|
Chris@102
|
34 #include <boost/archive/detail/decl.hpp>
|
Chris@102
|
35
|
Chris@102
|
36 #include <boost/archive/detail/abi_prefix.hpp> // must be the last headern
|
Chris@102
|
37
|
Chris@102
|
38 namespace boost_132 {
|
Chris@102
|
39 template<class T> class shared_ptr;
|
Chris@102
|
40 }
|
Chris@102
|
41 namespace boost {
|
Chris@102
|
42 namespace serialization {
|
Chris@102
|
43
|
Chris@102
|
44 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
Chris@102
|
45 template<class Archive, template<class U> class SPT >
|
Chris@102
|
46 void load(
|
Chris@102
|
47 Archive & ar,
|
Chris@102
|
48 SPT< class U > &t,
|
Chris@102
|
49 const unsigned int file_version
|
Chris@102
|
50 );
|
Chris@102
|
51 #endif
|
Chris@102
|
52
|
Chris@102
|
53 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
Chris@102
|
54 // a common class for holding various types of shared pointers
|
Chris@102
|
55
|
Chris@102
|
56 template<template<class T> class SPT>
|
Chris@102
|
57 class shared_ptr_helper {
|
Chris@102
|
58 typedef std::map<
|
Chris@102
|
59 const void *, // address of object
|
Chris@102
|
60 SPT<void> // address shared ptr to single instance
|
Chris@102
|
61 > object_shared_pointer_map;
|
Chris@102
|
62
|
Chris@102
|
63 // list of shared_pointers create accessable by raw pointer. This
|
Chris@102
|
64 // is used to "match up" shared pointers loaded at different
|
Chris@102
|
65 // points in the archive. Note, we delay construction until
|
Chris@102
|
66 // it is actually used since this is by default included as
|
Chris@102
|
67 // a "mix-in" even if shared_ptr isn't used.
|
Chris@102
|
68 object_shared_pointer_map * m_o_sp;
|
Chris@102
|
69
|
Chris@102
|
70 struct null_deleter {
|
Chris@102
|
71 void operator()(void const *) const {}
|
Chris@102
|
72 };
|
Chris@102
|
73
|
Chris@102
|
74 #if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) || defined(BOOST_MSVC)
|
Chris@102
|
75 public:
|
Chris@102
|
76 #else
|
Chris@102
|
77 template<class Archive, class U>
|
Chris@102
|
78 friend void boost::serialization::load(
|
Chris@102
|
79 Archive & ar,
|
Chris@102
|
80 SPT< U > &t,
|
Chris@102
|
81 const unsigned int file_version
|
Chris@102
|
82 );
|
Chris@102
|
83 #endif
|
Chris@102
|
84
|
Chris@102
|
85 #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
|
Chris@102
|
86 // list of loaded pointers. This is used to be sure that the pointers
|
Chris@102
|
87 // stay around long enough to be "matched" with other pointers loaded
|
Chris@102
|
88 // by the same archive. These are created with a "null_deleter" so that
|
Chris@102
|
89 // when this list is destroyed - the underlaying raw pointers are not
|
Chris@102
|
90 // destroyed. This has to be done because the pointers are also held by
|
Chris@102
|
91 // new system which is disjoint from this set. This is implemented
|
Chris@102
|
92 // by a change in load_construct_data below. It makes this file suitable
|
Chris@102
|
93 // only for loading pointers into a 1.33 or later boost system.
|
Chris@102
|
94 std::list<boost_132::shared_ptr<const void> > * m_pointers_132;
|
Chris@102
|
95 BOOST_ARCHIVE_DECL(void)
|
Chris@102
|
96 append(const boost_132::shared_ptr<const void> & t){
|
Chris@102
|
97 if(NULL == m_pointers_132)
|
Chris@102
|
98 m_pointers_132 = new std::list<boost_132::shared_ptr<const void> >;
|
Chris@102
|
99 m_pointers_132->push_back(t);
|
Chris@102
|
100 }
|
Chris@102
|
101 #endif
|
Chris@102
|
102
|
Chris@102
|
103 struct non_polymorphic {
|
Chris@102
|
104 template<class U>
|
Chris@102
|
105 static const boost::serialization::extended_type_info *
|
Chris@102
|
106 get_object_type(U & ){
|
Chris@102
|
107 return & boost::serialization::singleton<
|
Chris@102
|
108 typename
|
Chris@102
|
109 boost::serialization::type_info_implementation< U >::type
|
Chris@102
|
110 >::get_const_instance();
|
Chris@102
|
111 }
|
Chris@102
|
112 };
|
Chris@102
|
113 struct polymorphic {
|
Chris@102
|
114 template<class U>
|
Chris@102
|
115 static const boost::serialization::extended_type_info *
|
Chris@102
|
116 get_object_type(U & u){
|
Chris@102
|
117 return boost::serialization::singleton<
|
Chris@102
|
118 typename
|
Chris@102
|
119 boost::serialization::type_info_implementation< U >::type
|
Chris@102
|
120 >::get_const_instance().get_derived_extended_type_info(u);
|
Chris@102
|
121 }
|
Chris@102
|
122 };
|
Chris@102
|
123
|
Chris@102
|
124 public:
|
Chris@102
|
125 template<class T>
|
Chris@102
|
126 void reset(SPT< T > & s, T * t){
|
Chris@102
|
127 if(NULL == t){
|
Chris@102
|
128 s.reset();
|
Chris@102
|
129 return;
|
Chris@102
|
130 }
|
Chris@102
|
131 const boost::serialization::extended_type_info * this_type
|
Chris@102
|
132 = & boost::serialization::type_info_implementation< T >::type
|
Chris@102
|
133 ::get_const_instance();
|
Chris@102
|
134
|
Chris@102
|
135 // get pointer to the most derived object's eti. This is effectively
|
Chris@102
|
136 // the object type identifer
|
Chris@102
|
137 typedef typename mpl::if_<
|
Chris@102
|
138 is_polymorphic< T >,
|
Chris@102
|
139 polymorphic,
|
Chris@102
|
140 non_polymorphic
|
Chris@102
|
141 >::type type;
|
Chris@102
|
142
|
Chris@102
|
143 const boost::serialization::extended_type_info * true_type
|
Chris@102
|
144 = type::get_object_type(*t);
|
Chris@102
|
145
|
Chris@102
|
146 // note:if this exception is thrown, be sure that derived pointern
|
Chris@102
|
147 // is either registered or exported.
|
Chris@102
|
148 if(NULL == true_type)
|
Chris@102
|
149 boost::serialization::throw_exception(
|
Chris@102
|
150 boost::archive::archive_exception(
|
Chris@102
|
151 boost::archive::archive_exception::unregistered_class,
|
Chris@102
|
152 this_type->get_debug_info()
|
Chris@102
|
153 )
|
Chris@102
|
154 );
|
Chris@102
|
155 // get void pointer to the most derived type
|
Chris@102
|
156 // this uniquely identifies the object referred to
|
Chris@102
|
157 // oid = "object identifier"
|
Chris@102
|
158 const void * oid = void_downcast(
|
Chris@102
|
159 *true_type,
|
Chris@102
|
160 *this_type,
|
Chris@102
|
161 t
|
Chris@102
|
162 );
|
Chris@102
|
163 if(NULL == oid)
|
Chris@102
|
164 boost::serialization::throw_exception(
|
Chris@102
|
165 boost::archive::archive_exception(
|
Chris@102
|
166 boost::archive::archive_exception::unregistered_cast,
|
Chris@102
|
167 true_type->get_debug_info(),
|
Chris@102
|
168 this_type->get_debug_info()
|
Chris@102
|
169 )
|
Chris@102
|
170 );
|
Chris@102
|
171
|
Chris@102
|
172 // make tracking array if necessary
|
Chris@102
|
173 if(NULL == m_o_sp)
|
Chris@102
|
174 m_o_sp = new object_shared_pointer_map;
|
Chris@102
|
175
|
Chris@102
|
176 typename object_shared_pointer_map::iterator i = m_o_sp->find(oid);
|
Chris@102
|
177
|
Chris@102
|
178 // if it's a new object
|
Chris@102
|
179 if(i == m_o_sp->end()){
|
Chris@102
|
180 s.reset(t);
|
Chris@102
|
181 std::pair<typename object_shared_pointer_map::iterator, bool> result;
|
Chris@102
|
182 result = m_o_sp->insert(std::make_pair(oid, s));
|
Chris@102
|
183 BOOST_ASSERT(result.second);
|
Chris@102
|
184 }
|
Chris@102
|
185 // if the object has already been seen
|
Chris@102
|
186 else{
|
Chris@102
|
187 s = SPT<T>(i->second, t);
|
Chris@102
|
188 }
|
Chris@102
|
189 }
|
Chris@102
|
190
|
Chris@102
|
191 shared_ptr_helper() :
|
Chris@102
|
192 m_o_sp(NULL)
|
Chris@102
|
193 #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
|
Chris@102
|
194 , m_pointers_132(NULL)
|
Chris@102
|
195 #endif
|
Chris@102
|
196 {}
|
Chris@102
|
197 virtual ~shared_ptr_helper(){
|
Chris@102
|
198 if(NULL != m_o_sp)
|
Chris@102
|
199 delete m_o_sp;
|
Chris@102
|
200 #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
|
Chris@102
|
201 if(NULL != m_pointers_132)
|
Chris@102
|
202 delete m_pointers_132;
|
Chris@102
|
203 #endif
|
Chris@102
|
204 }
|
Chris@102
|
205 };
|
Chris@102
|
206
|
Chris@102
|
207 } // namespace serialization
|
Chris@102
|
208 } // namespace boost
|
Chris@102
|
209
|
Chris@102
|
210 #include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
|
Chris@102
|
211
|
Chris@102
|
212 #endif // BOOST_SERIALIZATION_SHARED_PTR_HELPER_HPP
|