source: NonGTP/Boost/boost/serialization/shared_ptr.hpp @ 857

Revision 857, 8.8 KB checked in by igarcia, 18 years ago (diff)
Line 
1#ifndef BOOST_SERIALIZATION_SHARED_PTR_HPP
2#define BOOST_SERIALIZATION_SHARED_PTR_HPP
3
4// MS compatible compilers support #pragma once
5#if defined(_MSC_VER) && (_MSC_VER >= 1020)
6# pragma once
7#endif
8
9/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
10// shared_ptr.hpp: serialization for boost shared pointer
11
12// (C) Copyright 2004 Robert Ramey and Martin Ecker
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
21#include <boost/config.hpp>
22#include <boost/mpl/integral_c.hpp>
23#include <boost/mpl/integral_c_tag.hpp>
24
25#include <boost/detail/workaround.hpp>
26#include <boost/shared_ptr.hpp>
27#include <boost/throw_exception.hpp>
28
29#include <boost/archive/archive_exception.hpp>
30
31// no extended type info system has been selected, use the typeid based one
32#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
33    #include <boost/serialization/extended_type_info_typeid.hpp>
34#endif
35#include <boost/serialization/type_info_implementation.hpp>
36#include <boost/serialization/split_free.hpp>
37#include <boost/serialization/nvp.hpp>
38#include <boost/serialization/version.hpp>
39#include <boost/serialization/tracking.hpp>
40#include <boost/static_assert.hpp>
41
42#include <boost/serialization/void_cast_fwd.hpp>
43
44/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
45// shared_ptr serialization traits
46// version 1 to distinguish from boost 1.32 version. Note: we can only do this
47// for a template when the compiler supports partial template specialization
48
49#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
50    namespace boost {
51    namespace serialization{
52        template<class T>
53        struct version< ::boost::shared_ptr<T> > {
54            typedef mpl::integral_c_tag tag;
55#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
56            typedef BOOST_DEDUCED_TYPENAME mpl::int_<1> type;
57#else
58            typedef mpl::int_<1> type;
59#endif
60#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
61            BOOST_STATIC_CONSTANT(unsigned int, value = 1);
62#else
63            BOOST_STATIC_CONSTANT(unsigned int, value = type::value);
64#endif
65        };
66        // don't track shared pointers
67        template<class T>
68        struct tracking_level< ::boost::shared_ptr<T> > {
69            typedef mpl::integral_c_tag tag;
70#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
71            typedef BOOST_DEDUCED_TYPENAME mpl::int_< ::boost::serialization::track_never> type;
72#else
73            typedef mpl::int_< ::boost::serialization::track_never> type;
74#endif
75#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
76            BOOST_STATIC_CONSTANT(int, value = ::boost::serialization::track_never);
77#else
78            BOOST_STATIC_CONSTANT(int, value = type::value);
79#endif
80        };
81    }}
82    #define BOOST_SERIALIZATION_SHARED_PTR(T)
83#else
84    // define macro to let users of these compilers do this
85    #define BOOST_SERIALIZATION_SHARED_PTR(T)                         \
86    BOOST_CLASS_VERSION(                                              \
87        ::boost::shared_ptr< T >,                                     \
88        1                                                             \
89    )                                                                 \
90    BOOST_CLASS_TRACKING(                                             \
91        ::boost::shared_ptr< T >,                                     \
92        ::boost::serialization::track_never                           \
93    )                                                                 \
94    /**/
95#endif
96
97namespace boost {
98namespace serialization{
99
100class extended_type_info;
101
102namespace detail {
103
104struct null_deleter {
105    void operator()(void const *) const {}
106};
107
108/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
109// a common class for holding various types of shared pointers
110
111class shared_ptr_helper {
112    typedef std::map<void*, shared_ptr<void> > collection_type;
113    typedef collection_type::const_iterator iterator_type;
114    // list of shared_pointers create accessable by raw pointer. This
115    // is used to "match up" shared pointers loaded at diferent
116    // points in the archive
117    collection_type m_pointers;
118    // return a void pointer to the most derived type
119    template<class T>
120    void * object_identifier(T * t) const {
121        const extended_type_info * true_type
122            = type_info_implementation<T>::type::get_derived_extended_type_info(*t);
123        // note:if this exception is thrown, be sure that derived pointer
124        // is either regsitered or exported.
125        if(NULL == true_type)
126            boost::throw_exception(
127                boost::archive::archive_exception(
128                    boost::archive::archive_exception::unregistered_class
129                )
130            );
131        const boost::serialization::extended_type_info * this_type
132            = boost::serialization::type_info_implementation<T>::type::get_instance();
133        void * vp = void_downcast(*true_type, *this_type, t);
134        return vp;
135    }
136public:
137    template<class T>
138    void reset(shared_ptr<T> & s, T * r){
139        if(NULL == r){
140            s.reset();
141            return;
142        }
143        // get pointer to the most derived object.  This is effectively
144        // the object identifer
145        void * od = object_identifier(r);
146
147        iterator_type it = m_pointers.find(od);
148
149        if(it == m_pointers.end()){
150            s.reset(r);
151            m_pointers.insert(collection_type::value_type(od,s));
152        }
153        else{
154            s = static_pointer_cast<T>((*it).second);
155        }
156    }
157    virtual ~shared_ptr_helper(){}
158};
159
160} // namespace detail
161
162/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
163// utility function for creating/getting a helper - could be useful in general
164// but shared_ptr is the only class (so far that needs it) and I don't have a
165// convenient header to place it into.
166template<class Archive, class H>
167H &
168get_helper(Archive & ar){
169    extended_type_info * eti = type_info_implementation<H>::type::get_instance();
170    shared_ptr<void> sph;
171    ar.lookup_helper(eti, sph);
172    if(NULL == sph.get()){
173        sph = shared_ptr<H>(new H);
174        ar.insert_helper(eti, sph);
175    }
176    return * static_cast<H *>(sph.get());
177}
178
179/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
180// serialization for shared_ptr
181
182template<class Archive, class T>
183inline void save(
184    Archive & ar,
185    const boost::shared_ptr<T> &t,
186    const unsigned int /* file_version */
187){
188    // The most common cause of trapping here would be serializing
189    // something like shared_ptr<int>.  This occurs because int
190    // is never tracked by default.  Wrap int in a trackable type
191    BOOST_STATIC_ASSERT((tracking_level<T>::value != track_never));
192    const T * t_ptr = t.get();
193    ar << boost::serialization::make_nvp("px", t_ptr);
194}
195
196template<class Archive, class T>
197inline void load(
198    Archive & ar,
199    boost::shared_ptr<T> &t,
200    const unsigned int file_version
201){
202    // The most common cause of trapping here would be serializing
203    // something like shared_ptr<int>.  This occurs because int
204    // is never tracked by default.  Wrap int in a trackable type
205    BOOST_STATIC_ASSERT((tracking_level<T>::value != track_never));
206    T* r;
207    #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
208    if(file_version < 1){
209        ar.register_type(static_cast<
210            boost_132::detail::sp_counted_base_impl<T *, boost::checked_deleter<T> > *
211        >(NULL));
212        boost_132::shared_ptr<T> sp;
213        ar >> boost::serialization::make_nvp("px", sp.px);
214        ar >> boost::serialization::make_nvp("pn", sp.pn);
215        // got to keep the sps around so the sp.pns don't disappear
216        get_helper<Archive, boost_132::serialization::detail::shared_ptr_helper>(ar).append(sp);
217        r = sp.get();
218    }
219    else   
220    #endif
221    {
222        ar >> boost::serialization::make_nvp("px", r);
223    }
224    get_helper<Archive, detail::shared_ptr_helper >(ar).reset(t,r);
225}
226
227template<class Archive, class T>
228inline void serialize(
229    Archive & ar,
230    boost::shared_ptr<T> &t,
231    const unsigned int file_version
232){
233    // correct shared_ptr serialization depends upon object tracking
234    // being used.
235    BOOST_STATIC_ASSERT(
236        boost::serialization::tracking_level<T>::value
237        != boost::serialization::track_never
238    );
239    boost::serialization::split_free(ar, t, file_version);
240}
241
242} // namespace serialization
243} // namespace boost
244
245#endif // BOOST_SERIALIZATION_SHARED_PTR_HPP
Note: See TracBrowser for help on using the repository browser.