shared_ptr_helper.hpp 6.9 KB

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