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