Ticket #1418: kab-080910-cross-cast.patch
File kab-080910-cross-cast.patch, 17.3 KB (added by , 14 years ago) |
---|
-
boost/archive/detail/archive_cast.hpp
diff -Naur ../boost_1_34_1-orig/boost/archive/detail/archive_cast.hpp ./boost/archive/detail/archive_cast.hpp
old new 1 #ifndef BOOST_ARCHIVE_DETAIL_ARCHIVE_CAST_HPP 2 #define BOOST_ARCHIVE_DETAIL_ARCHIVE_CAST_HPP 3 4 // MS compatible compilers support #pragma once 5 #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 # pragma once 7 #endif 8 9 // archive_cast.hpp 10 11 // (C) Copyright 2007 Kim Barrett - kab@irobot.com 12 // Use, modification and distribution is subject to the Boost Software 13 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 14 // http://www.boost.org/LICENSE_1_0.txt) 15 16 #include <boost/config.hpp> 17 #include <boost/smart_cast.hpp> 18 #include <boost/type_traits/is_base_and_derived.hpp> 19 20 #include <boost/archive/detail/abi_prefix.hpp> // must be the last header 21 22 // helper for [i,o]serializers, allowing them to route operation to the 23 // appropriate specialized archive class. the purpose of archive_cast is to 24 // provide the serializer with a means of converting a reference to the 25 // basic_[i,o]archive to the appropriate archive class for further 26 // serialization. 27 // 28 // the Archive type must be the same type for all serialization calls 29 // applied to a given archive. if the archive is non-polymorphic, the Archive 30 // type must always be the most derived type of the archive. if the archive 31 // is polymorphic, the Archive type should always be the polymorphic archive 32 // type, else there would be little point in using a polymorphic archive type. 33 // 34 // in the non-polymorphic case, because Archive is the most derived archive 35 // type, which is (indirectly) derived from the basic archive class, the 36 // operation is a (supposedly safe) downcast. 37 // 38 // in the polymorphic case, Archive is the polymorphic archive class (or 39 // possibly something derived from it), and the obvious conversion is a 40 // dynamic_cast. however, in this case that dynamic_cast is a cross-cast, 41 // because the polymorphic archive class and the basic archive class are not 42 // in a base and derived relationship (in either order). cross-casts may be 43 // extremely expensive on some platforms, so a different approach is desired. 44 // 45 // archive_caster provides deferrable conversion of a basic_[i,o]archive to 46 // Archive. the cast function returns the result of that conversion as a 47 // void*. the conversion to void* permits the value to be stored in a location 48 // that has no information about Archive, with a later static cast from that 49 // void* to Archive*. 50 // 51 // archive_cast_pointer provides the customization point for the 52 // basic_[i,o]archive classes. the intended implementation is to cache the 53 // result of the caster in the basic archive on the first call, and use the 54 // previously cached result thereafter. 55 // 56 // archive_cast_impl provides a level of indirection so that archive_cast 57 // only instantiates the archive_caster template when actually needed, and 58 // not in the case where Archive is derived from From. 59 60 namespace boost { 61 namespace archive { 62 namespace detail { 63 64 template<class Archive, class From> 65 struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_caster { 66 // out of line implementation in impl/archive_cast.ipp. 67 static void* cast(From& ar); 68 }; 69 70 template<class From> 71 struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_cast_pointer { 72 // out of line implementations for each relevant From class 73 static void* get(From& ar, void* (*caster)(From& ar)); 74 }; 75 76 template<class From, bool is_derived> 77 struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_cast_impl; 78 79 template<class From> 80 struct archive_cast_impl<From, true> { // Archive derived from From 81 template<class Archive> 82 static Archive& cast(From& ar) { 83 return boost::smart_cast_reference<Archive&>(ar); 84 } 85 }; 86 87 template<class From> 88 struct archive_cast_impl<From, false> { // Archive not derived from From 89 template<class Archive> 90 static Archive& cast(From& ar) { 91 return *static_cast<Archive*>( 92 archive_cast_pointer<From>::get( 93 ar, 94 archive_caster<Archive, From>::cast)); 95 } 96 }; 97 98 template<class Archive, class From> 99 inline Archive& archive_cast(From& ar) { 100 // select implementation based on whether Archive is derived from From 101 return archive_cast_impl< 102 From, 103 boost::is_base_and_derived<From, Archive>::value 104 >::template cast<Archive>(ar); 105 } 106 107 } // namespace detail 108 } // namespace archive 109 } // namespace boost 110 111 #include <boost/archive/detail/abi_suffix.hpp> // pops abi_prefix.hpp pragmas 112 113 #endif // include guard -
boost/archive/detail/basic_iarchive.hpp
diff -Naur ../boost_1_34_1-orig/boost/archive/detail/basic_iarchive.hpp ./boost/archive/detail/basic_iarchive.hpp
old new 21 21 22 22 #include <boost/config.hpp> 23 23 #include <boost/archive/basic_archive.hpp> 24 #include <boost/archive/detail/archive_cast.hpp> 24 25 #include <boost/serialization/tracking_enum.hpp> 25 26 26 27 #include <boost/archive/detail/abi_prefix.hpp> // must be the last header … … 43 44 // class basic_iarchive - read serialized objects from a input stream 44 45 class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive 45 46 { 47 friend class archive_cast_pointer<basic_iarchive>; 46 48 friend class basic_iarchive_impl; 47 49 // hide implementation of this class to minimize header conclusion 48 50 // in client code. I couldn't used scoped pointer with borland -
boost/archive/detail/basic_oarchive.hpp
diff -Naur ../boost_1_34_1-orig/boost/archive/detail/basic_oarchive.hpp ./boost/archive/detail/basic_oarchive.hpp
old new 23 23 // #include <boost/scoped_ptr.hpp> 24 24 25 25 #include <boost/archive/basic_archive.hpp> 26 #include <boost/archive/detail/archive_cast.hpp> 26 27 #include <boost/serialization/tracking_enum.hpp> 27 28 28 29 #include <boost/archive/detail/abi_prefix.hpp> // must be the last header … … 45 46 // class basic_oarchive - write serialized objects to an output stream 46 47 class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive 47 48 { 49 friend class archive_cast_pointer<basic_oarchive>; 48 50 friend class basic_oarchive_impl; 49 51 // hide implementation of this class to minimize header conclusion 50 52 // in client code. note: borland can't use scoped_ptr -
boost/archive/detail/iserializer.hpp
diff -Naur ../boost_1_34_1-orig/boost/archive/detail/iserializer.hpp ./boost/archive/detail/iserializer.hpp
old new 63 63 #endif 64 64 // the following is need only for dynamic cast of polymorphic pointers 65 65 #include <boost/archive/detail/basic_iarchive.hpp> 66 #include <boost/archive/detail/archive_cast.hpp> 66 67 #include <boost/archive/detail/basic_iserializer.hpp> 67 68 #include <boost/archive/detail/archive_pointer_iserializer.hpp> 68 69 #include <boost/archive/archive_exception.hpp> … … 156 157 // make sure call is routed through the higest interface that might 157 158 // be specialized by the user. 158 159 boost::serialization::serialize_adl( 159 boost::smart_cast_reference<Archive &>(ar),160 archive_cast<Archive>(ar), 160 161 * static_cast<T *>(x), 161 162 file_version 162 163 ); … … 284 285 void * & x, 285 286 const unsigned int file_version 286 287 ) const { 287 Archive & ar_impl = boost::smart_cast_reference<Archive &>(ar);288 Archive & ar_impl = archive_cast<Archive>(ar); 288 289 289 290 // if(0 != (ar.get_flags() & no_object_creation)){ 290 291 // ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(x)); -
boost/archive/detail/oserializer.hpp
diff -Naur ../boost_1_34_1-orig/boost/archive/detail/oserializer.hpp ./boost/archive/detail/oserializer.hpp
old new 55 55 #endif 56 56 // the following is need only for dynamic cast of polymorphic pointers 57 57 #include <boost/archive/detail/basic_oarchive.hpp> 58 #include <boost/archive/detail/archive_cast.hpp> 58 59 #include <boost/archive/detail/basic_oserializer.hpp> 59 60 #include <boost/archive/detail/archive_pointer_oserializer.hpp> 60 61 … … 145 146 // make sure call is routed through the highest interface that might 146 147 // be specialized by the user. 147 148 boost::serialization::serialize_adl( 148 boost::smart_cast_reference<Archive &>(ar),149 archive_cast<Archive>(ar), 149 150 * static_cast<T *>(const_cast<void *>(x)), 150 151 version() 151 152 ); … … 206 207 // be specialized by the user. 207 208 T * t = static_cast<T *>(const_cast<void *>(x)); 208 209 const unsigned int file_version = boost::serialization::version<T>::value; 209 Archive & ar_impl = boost::smart_cast_reference<Archive &>(ar);210 Archive & ar_impl = archive_cast<Archive>(ar); 210 211 boost::serialization::save_construct_data_adl<Archive, T>( 211 212 ar_impl, 212 213 t, -
boost/archive/impl/archive_cast.ipp
diff -Naur ../boost_1_34_1-orig/boost/archive/impl/archive_cast.ipp ./boost/archive/impl/archive_cast.ipp
old new 1 // archive_cast.ipp 2 3 // (C) Copyright 2007 Kim Barrett - kab@irobot.com 4 // Use, modification and distribution is subject to the Boost Software 5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 8 #include <boost/config.hpp> // msvc 6.0 needs this for warning suppression 9 10 #include <boost/archive/detail/archive_cast.hpp> 11 12 namespace boost { 13 namespace archive { 14 namespace detail { 15 16 template<class Archive, class From> 17 void* archive_caster<Archive, From>::cast(From& ar) { 18 return & dynamic_cast<Archive &>(ar); 19 } 20 21 } // namespace detail 22 } // namespace archive 23 } // namespace boost -
libs/serialization/src/basic_iarchive.cpp
diff -Naur ../boost_1_34_1-orig/libs/serialization/src/basic_iarchive.cpp ./libs/serialization/src/basic_iarchive.cpp
old new 34 34 #include <boost/archive/detail/basic_pointer_iserializer.hpp> 35 35 #include <boost/archive/detail/basic_iarchive.hpp> 36 36 #include <boost/archive/detail/basic_archive_impl.hpp> 37 #include <boost/archive/detail/archive_cast.hpp> 37 38 #include <boost/archive/archive_exception.hpp> 38 39 39 40 #include <boost/serialization/tracking.hpp> … … 52 53 public basic_archive_impl 53 54 { 54 55 friend class basic_iarchive; 56 friend class archive_cast_pointer<basic_iarchive>; 55 57 56 58 version_type m_archive_library_version; 57 59 unsigned int m_flags; 60 void* (*m_cached_archive_caster)(basic_iarchive&); 61 void* m_cached_archive_cast_pointer; 58 62 59 63 ////////////////////////////////////////////////////////////////////// 60 64 // information about each serialized object loaded … … 197 201 basic_iarchive_impl(unsigned int flags) : 198 202 m_archive_library_version(ARCHIVE_VERSION()), 199 203 m_flags(flags), 204 m_cached_archive_caster(NULL), 205 m_cached_archive_cast_pointer(NULL), 200 206 moveable_objects_start(0), 201 207 moveable_objects_end(0), 208 // kab, 11/12/2007: added following line, per iRobot PR#2955. 209 moveable_objects_recent(0), 202 210 pending_object(NULL), 203 211 pending_bis(NULL), 204 212 pending_version(0) … … 294 302 reinterpret_cast<std::size_t>(new_address) - member_displacement 295 303 ); 296 304 } 297 ++i; 305 // kab, 11/12/2007: following line commented out, per iRobot PR#2609. 306 // ++i; 298 307 } 299 308 } 300 309 … … 607 616 return pimpl->m_flags; 608 617 } 609 618 619 // this is identical to the corresponding basic_oarchive function. 620 // it would be nice if they could be merged into one parameterized definition, 621 // but doing so seems more work than accepting and noting the duplication. 622 template<> 623 BOOST_ARCHIVE_DECL(void*) 624 archive_cast_pointer<basic_iarchive>::get( 625 basic_iarchive& ar, void* (*caster)(basic_iarchive&)) 626 { 627 void* result = ar.pimpl->m_cached_archive_cast_pointer; 628 if (result) { 629 // already cached. 630 // if debug build, verify called with same caster. 631 assert(caster == ar.pimpl->m_cached_archive_caster); 632 // if debug build, verify cached result matches caster result. 633 // otherwise, assume it does and skip expensive cast 634 assert(result == caster(ar)); 635 } else { 636 // on first call, use the caster's result and cache for later reuse. 637 result = caster(ar); 638 ar.pimpl->m_cached_archive_caster = caster; 639 ar.pimpl->m_cached_archive_cast_pointer = result; 640 } 641 return result; 642 } 643 610 644 } // namespace detail 611 645 } // namespace archive 612 646 } // namespace boost -
libs/serialization/src/basic_oarchive.cpp
diff -Naur ../boost_1_34_1-orig/libs/serialization/src/basic_oarchive.cpp ./libs/serialization/src/basic_oarchive.cpp
old new 26 26 #include <boost/archive/detail/basic_pointer_oserializer.hpp> 27 27 #include <boost/archive/detail/basic_oarchive.hpp> 28 28 #include <boost/archive/detail/basic_archive_impl.hpp> 29 #include <boost/archive/detail/archive_cast.hpp> 29 30 #include <boost/archive/archive_exception.hpp> 30 31 31 32 #ifdef BOOST_MSVC … … 49 50 public basic_archive_impl 50 51 { 51 52 friend class basic_oarchive; 53 friend class archive_cast_pointer<basic_oarchive>; 52 54 53 55 unsigned int m_flags; 56 void* (*m_cached_archive_caster)(basic_oarchive&); 57 void* m_cached_archive_cast_pointer; 54 58 55 59 ////////////////////////////////////////////////////////////////////// 56 60 // information about each serialized object saved … … 143 147 144 148 basic_oarchive_impl(unsigned int flags) : 145 149 m_flags(flags), 150 m_cached_archive_caster(NULL), 151 m_cached_archive_cast_pointer(NULL), 146 152 pending_object(NULL), 147 153 pending_bos(NULL) 148 154 {} … … 454 460 basic_oarchive::end_preamble(){ 455 461 } 456 462 463 // this is identical to the corresponding basic_iarchive function. 464 // it would be nice if they could be merged into one parameterized definition, 465 // but doing so seems more work than accepting and noting the duplication. 466 template<> 467 BOOST_ARCHIVE_DECL(void*) 468 archive_cast_pointer<basic_oarchive>::get( 469 basic_oarchive& ar, void* (*caster)(basic_oarchive&)) 470 { 471 void* result = ar.pimpl->m_cached_archive_cast_pointer; 472 if (result) { 473 // already cached. 474 // if debug build, verify called with same caster. 475 assert(caster == ar.pimpl->m_cached_archive_caster); 476 // if debug build, verify cached result matches caster result. 477 // otherwise, assume it does and skip expensive cast 478 assert(result == caster(ar)); 479 } else { 480 // on first call, use the caster's result and cache for later reuse. 481 result = caster(ar); 482 ar.pimpl->m_cached_archive_caster = caster; 483 ar.pimpl->m_cached_archive_cast_pointer = result; 484 } 485 return result; 486 } 487 457 488 } // namespace detail 458 489 } // namespace archive 459 490 } // namespace boost -
libs/serialization/src/polymorphic_iarchive.cpp
diff -Naur ../boost_1_34_1-orig/libs/serialization/src/polymorphic_iarchive.cpp ./libs/serialization/src/polymorphic_iarchive.cpp
old new 20 20 // explicitly instantiate for this type of text stream 21 21 #include <boost/archive/impl/archive_pointer_iserializer.ipp> 22 22 23 // explicitly instantiate archive_caster for this type 24 #include <boost/archive/impl/archive_cast.ipp> 25 #include <boost/archive/detail/basic_iarchive.hpp> 26 23 27 namespace boost { 24 28 namespace archive { 29 namespace detail { 25 30 26 template class detail::archive_pointer_iserializer<polymorphic_iarchive> ; 31 template class archive_pointer_iserializer<polymorphic_iarchive> ; 32 template class archive_caster<polymorphic_iarchive, basic_iarchive> ; 27 33 34 } // namespace detail 28 35 } // namespace serialization 29 36 } // namespace boost -
libs/serialization/src/polymorphic_oarchive.cpp
diff -Naur ../boost_1_34_1-orig/libs/serialization/src/polymorphic_oarchive.cpp ./libs/serialization/src/polymorphic_oarchive.cpp
old new 20 20 // explicitly instantiate for this type of text stream 21 21 #include <boost/archive/impl/archive_pointer_oserializer.ipp> 22 22 23 // explicitly instantiate archive_caster for this type 24 #include <boost/archive/impl/archive_cast.ipp> 25 #include <boost/archive/detail/basic_oarchive.hpp> 26 23 27 namespace boost { 24 28 namespace archive { 29 namespace detail { 25 30 26 template class detail::archive_pointer_oserializer<polymorphic_oarchive> ; 31 template class archive_pointer_oserializer<polymorphic_oarchive> ; 32 template class archive_caster<polymorphic_oarchive, basic_oarchive> ; 27 33 34 } // namespace detail 28 35 } // namespace archive 29 36 } // namespace boost