Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / serialization / shared_ptr_helper.hpp
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 {
68         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
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 * 
105         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 * 
115         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>
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
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     {}
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