sl@0: #ifndef BOOST_SERIALIZATION_SHARED_PTR_HPP sl@0: #define BOOST_SERIALIZATION_SHARED_PTR_HPP sl@0: sl@0: // MS compatible compilers support #pragma once sl@0: #if defined(_MSC_VER) && (_MSC_VER >= 1020) sl@0: # pragma once sl@0: #endif sl@0: sl@0: /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 sl@0: // shared_ptr.hpp: serialization for boost shared pointer sl@0: sl@0: // (C) Copyright 2004 Robert Ramey and Martin Ecker sl@0: // Use, modification and distribution is subject to the Boost Software sl@0: // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at sl@0: // http://www.boost.org/LICENSE_1_0.txt) sl@0: sl@0: // See http://www.boost.org for updates, documentation, and revision history. sl@0: sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include sl@0: sl@0: /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 sl@0: // shared_ptr serialization traits sl@0: // version 1 to distinguish from boost 1.32 version. Note: we can only do this sl@0: // for a template when the compiler supports partial template specialization sl@0: sl@0: #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION sl@0: namespace boost { sl@0: namespace serialization{ sl@0: template sl@0: struct version< ::boost::shared_ptr > { sl@0: typedef mpl::integral_c_tag tag; sl@0: #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) sl@0: typedef BOOST_DEDUCED_TYPENAME mpl::int_<1> type; sl@0: #else sl@0: typedef mpl::int_<1> type; sl@0: #endif sl@0: #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)) sl@0: BOOST_STATIC_CONSTANT(unsigned int, value = 1); sl@0: #else sl@0: BOOST_STATIC_CONSTANT(unsigned int, value = type::value); sl@0: #endif sl@0: }; sl@0: // don't track shared pointers sl@0: template sl@0: struct tracking_level< ::boost::shared_ptr > { sl@0: typedef mpl::integral_c_tag tag; sl@0: #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) sl@0: typedef BOOST_DEDUCED_TYPENAME mpl::int_< ::boost::serialization::track_never> type; sl@0: #else sl@0: typedef mpl::int_< ::boost::serialization::track_never> type; sl@0: #endif sl@0: #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)) sl@0: BOOST_STATIC_CONSTANT(int, value = ::boost::serialization::track_never); sl@0: #else sl@0: BOOST_STATIC_CONSTANT(int, value = type::value); sl@0: #endif sl@0: }; sl@0: }} sl@0: #define BOOST_SERIALIZATION_SHARED_PTR(T) sl@0: #else sl@0: // define macro to let users of these compilers do this sl@0: #define BOOST_SERIALIZATION_SHARED_PTR(T) \ sl@0: BOOST_CLASS_VERSION( \ sl@0: ::boost::shared_ptr< T >, \ sl@0: 1 \ sl@0: ) \ sl@0: BOOST_CLASS_TRACKING( \ sl@0: ::boost::shared_ptr< T >, \ sl@0: ::boost::serialization::track_never \ sl@0: ) \ sl@0: /**/ sl@0: #endif sl@0: sl@0: namespace boost { sl@0: namespace serialization{ sl@0: sl@0: class extended_type_info; sl@0: sl@0: namespace detail { sl@0: sl@0: struct null_deleter { sl@0: void operator()(void const *) const {} sl@0: }; sl@0: sl@0: /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 sl@0: // a common class for holding various types of shared pointers sl@0: sl@0: class shared_ptr_helper { sl@0: typedef std::map > collection_type; sl@0: typedef collection_type::const_iterator iterator_type; sl@0: // list of shared_pointers create accessable by raw pointer. This sl@0: // is used to "match up" shared pointers loaded at diferent sl@0: // points in the archive sl@0: collection_type m_pointers; sl@0: // return a void pointer to the most derived type sl@0: template sl@0: void * object_identifier(T * t) const { sl@0: const extended_type_info * true_type sl@0: = type_info_implementation::type::get_derived_extended_type_info(*t); sl@0: // note:if this exception is thrown, be sure that derived pointer sl@0: // is either regsitered or exported. sl@0: if(NULL == true_type) sl@0: boost::throw_exception( sl@0: boost::archive::archive_exception( sl@0: boost::archive::archive_exception::unregistered_class sl@0: ) sl@0: ); sl@0: const boost::serialization::extended_type_info * this_type sl@0: = boost::serialization::type_info_implementation::type::get_instance(); sl@0: void * vp = void_downcast(*true_type, *this_type, t); sl@0: return vp; sl@0: } sl@0: public: sl@0: template sl@0: void reset(shared_ptr & s, T * r){ sl@0: if(NULL == r){ sl@0: s.reset(); sl@0: return; sl@0: } sl@0: // get pointer to the most derived object. This is effectively sl@0: // the object identifer sl@0: void * od = object_identifier(r); sl@0: sl@0: iterator_type it = m_pointers.find(od); sl@0: sl@0: if(it == m_pointers.end()){ sl@0: s.reset(r); sl@0: m_pointers.insert(collection_type::value_type(od,s)); sl@0: } sl@0: else{ sl@0: s = static_pointer_cast((*it).second); sl@0: } sl@0: } sl@0: virtual ~shared_ptr_helper(){} sl@0: }; sl@0: sl@0: } // namespace detail sl@0: sl@0: /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 sl@0: // utility function for creating/getting a helper - could be useful in general sl@0: // but shared_ptr is the only class (so far that needs it) and I don't have a sl@0: // convenient header to place it into. sl@0: template sl@0: H & sl@0: get_helper(Archive & ar){ sl@0: extended_type_info * eti = type_info_implementation::type::get_instance(); sl@0: shared_ptr sph; sl@0: ar.lookup_helper(eti, sph); sl@0: if(NULL == sph.get()){ sl@0: sph = shared_ptr(new H); sl@0: ar.insert_helper(eti, sph); sl@0: } sl@0: return * static_cast(sph.get()); sl@0: } sl@0: sl@0: /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 sl@0: // serialization for shared_ptr sl@0: sl@0: template sl@0: inline void save( sl@0: Archive & ar, sl@0: const boost::shared_ptr &t, sl@0: const unsigned int /* file_version */ sl@0: ){ sl@0: // The most common cause of trapping here would be serializing sl@0: // something like shared_ptr. This occurs because int sl@0: // is never tracked by default. Wrap int in a trackable type sl@0: BOOST_STATIC_ASSERT((tracking_level::value != track_never)); sl@0: const T * t_ptr = t.get(); sl@0: ar << boost::serialization::make_nvp("px", t_ptr); sl@0: } sl@0: sl@0: template sl@0: inline void load( sl@0: Archive & ar, sl@0: boost::shared_ptr &t, sl@0: const unsigned int file_version sl@0: ){ sl@0: // The most common cause of trapping here would be serializing sl@0: // something like shared_ptr. This occurs because int sl@0: // is never tracked by default. Wrap int in a trackable type sl@0: BOOST_STATIC_ASSERT((tracking_level::value != track_never)); sl@0: T* r; sl@0: #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP sl@0: if(file_version < 1){ sl@0: ar.register_type(static_cast< sl@0: boost_132::detail::sp_counted_base_impl > * sl@0: >(NULL)); sl@0: boost_132::shared_ptr sp; sl@0: ar >> boost::serialization::make_nvp("px", sp.px); sl@0: ar >> boost::serialization::make_nvp("pn", sp.pn); sl@0: // got to keep the sps around so the sp.pns don't disappear sl@0: get_helper(ar).append(sp); sl@0: r = sp.get(); sl@0: } sl@0: else sl@0: #endif sl@0: { sl@0: ar >> boost::serialization::make_nvp("px", r); sl@0: } sl@0: get_helper(ar).reset(t,r); sl@0: } sl@0: sl@0: template sl@0: inline void serialize( sl@0: Archive & ar, sl@0: boost::shared_ptr &t, sl@0: const unsigned int file_version sl@0: ){ sl@0: // correct shared_ptr serialization depends upon object tracking sl@0: // being used. sl@0: BOOST_STATIC_ASSERT( sl@0: boost::serialization::tracking_level::value sl@0: != boost::serialization::track_never sl@0: ); sl@0: boost::serialization::split_free(ar, t, file_version); sl@0: } sl@0: sl@0: } // namespace serialization sl@0: } // namespace boost sl@0: sl@0: #endif // BOOST_SERIALIZATION_SHARED_PTR_HPP