Ticket #1418: kab-071107-cross-cast.patch

File kab-071107-cross-cast.patch, 16.9 KB (added by Kim Barrett <kab@…>, 15 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
     60namespace boost {
     61namespace archive {
     62namespace detail {
     63
     64template<class Archive, class From>
     65struct 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
     70template<class From>
     71struct 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
     76template<class From, bool is_derived>
     77struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_cast_impl;
     78
     79template<class From>
     80struct 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
     87template<class From>
     88struct 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
     98template<class Archive, class From>
     99inline 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  
    2121
    2222#include <boost/config.hpp>
    2323#include <boost/archive/basic_archive.hpp>
     24#include <boost/archive/detail/archive_cast.hpp>
    2425#include <boost/serialization/tracking_enum.hpp>
    2526
    2627#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
     
    4344// class basic_iarchive - read serialized objects from a input stream
    4445class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive
    4546{
     47    friend class archive_cast_pointer<basic_iarchive>;
    4648    friend class basic_iarchive_impl;
    4749    // hide implementation of this class to minimize header conclusion
    4850    // 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  
    2323// #include <boost/scoped_ptr.hpp>
    2424
    2525#include <boost/archive/basic_archive.hpp>
     26#include <boost/archive/detail/archive_cast.hpp>
    2627#include <boost/serialization/tracking_enum.hpp>
    2728
    2829#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
     
    4546// class basic_oarchive - write serialized objects to an output stream
    4647class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive
    4748{
     49    friend class archive_cast_pointer<basic_oarchive>;
    4850    friend class basic_oarchive_impl;
    4951    // hide implementation of this class to minimize header conclusion
    5052    // 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  
    6363 #endif
    6464// the following is need only for dynamic cast of polymorphic pointers
    6565#include <boost/archive/detail/basic_iarchive.hpp>
     66#include <boost/archive/detail/archive_cast.hpp>
    6667#include <boost/archive/detail/basic_iserializer.hpp>
    6768#include <boost/archive/detail/archive_pointer_iserializer.hpp>
    6869#include <boost/archive/archive_exception.hpp>
     
    156157    // make sure call is routed through the higest interface that might
    157158    // be specialized by the user.
    158159    boost::serialization::serialize_adl(
    159         boost::smart_cast_reference<Archive &>(ar),
     160        archive_cast<Archive>(ar),
    160161        * static_cast<T *>(x),
    161162        file_version
    162163    );
     
    284285    void * & x,
    285286    const unsigned int file_version
    286287) const {
    287     Archive & ar_impl = boost::smart_cast_reference<Archive &>(ar);
     288    Archive & ar_impl = archive_cast<Archive>(ar);
    288289
    289290//    if(0 != (ar.get_flags() & no_object_creation)){
    290291//        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  
    5555 #endif
    5656// the following is need only for dynamic cast of polymorphic pointers
    5757#include <boost/archive/detail/basic_oarchive.hpp>
     58#include <boost/archive/detail/archive_cast.hpp>
    5859#include <boost/archive/detail/basic_oserializer.hpp>
    5960#include <boost/archive/detail/archive_pointer_oserializer.hpp>
    6061
     
    145146    // make sure call is routed through the highest interface that might
    146147    // be specialized by the user.
    147148    boost::serialization::serialize_adl(
    148         boost::smart_cast_reference<Archive &>(ar),
     149        archive_cast<Archive>(ar),
    149150        * static_cast<T *>(const_cast<void *>(x)),
    150151        version()
    151152    );
     
    206207    // be specialized by the user.
    207208    T * t = static_cast<T *>(const_cast<void *>(x));
    208209    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);
    210211    boost::serialization::save_construct_data_adl<Archive, T>(
    211212        ar_impl,
    212213        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
     12namespace boost {
     13namespace archive {
     14namespace detail {
     15
     16template<class Archive, class From>
     17void* 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  
    3434#include <boost/archive/detail/basic_pointer_iserializer.hpp>
    3535#include <boost/archive/detail/basic_iarchive.hpp>
    3636#include <boost/archive/detail/basic_archive_impl.hpp>
     37#include <boost/archive/detail/archive_cast.hpp>
    3738#include <boost/archive/archive_exception.hpp>
    3839
    3940#include <boost/serialization/tracking.hpp>
     
    5253    public basic_archive_impl
    5354{
    5455    friend class basic_iarchive;
     56    friend class archive_cast_pointer<basic_iarchive>;
    5557
    5658    version_type m_archive_library_version;
    5759    unsigned int m_flags;
     60    void* (*m_cached_archive_caster)(basic_iarchive&);
     61    void* m_cached_archive_cast_pointer;
    5862
    5963    //////////////////////////////////////////////////////////////////////
    6064    // information about each serialized object loaded
     
    197201    basic_iarchive_impl(unsigned int flags) :
    198202        m_archive_library_version(ARCHIVE_VERSION()),
    199203        m_flags(flags),
     204        m_cached_archive_caster(NULL),
     205        m_cached_archive_cast_pointer(NULL),
    200206        moveable_objects_start(0),
    201207        moveable_objects_end(0),
    202208        pending_object(NULL),
     
    607613    return pimpl->m_flags;
    608614}
    609615
     616// this is identical to the corresponding basic_oarchive function.
     617// it would be nice if they could be merged into one parameterized definition,
     618// but doing so seems more work than accepting and noting the duplication.
     619template<>
     620BOOST_ARCHIVE_DECL(void*)
     621archive_cast_pointer<basic_iarchive>::get(
     622    basic_iarchive& ar, void* (*caster)(basic_iarchive&))
     623{
     624    void* result = ar.pimpl->m_cached_archive_cast_pointer;
     625    if (result) {
     626        // already cached.
     627        // if debug build, verify called with same caster.
     628        assert(caster != ar.pimpl->m_cached_archive_caster);
     629        // if debug build, verify cached result matches caster result.
     630        // otherwise, assume it does and skip expensive cast
     631        assert(result == caster(ar));
     632    } else {
     633        // on first call, use the caster's result and cache for later reuse.
     634        result = caster(ar);
     635        ar.pimpl->m_cached_archive_caster = caster;
     636        ar.pimpl->m_cached_archive_cast_pointer = result;
     637    }
     638    return result;
     639}
     640
    610641} // namespace detail
    611642} // namespace archive
    612643} // 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  
    2626#include <boost/archive/detail/basic_pointer_oserializer.hpp>
    2727#include <boost/archive/detail/basic_oarchive.hpp>
    2828#include <boost/archive/detail/basic_archive_impl.hpp>
     29#include <boost/archive/detail/archive_cast.hpp>
    2930#include <boost/archive/archive_exception.hpp>
    3031
    3132#ifdef BOOST_MSVC
     
    4950    public basic_archive_impl
    5051{
    5152    friend class basic_oarchive;
     53    friend class archive_cast_pointer<basic_oarchive>;
    5254
    5355    unsigned int m_flags;
     56    void* (*m_cached_archive_caster)(basic_oarchive&);
     57    void* m_cached_archive_cast_pointer;
    5458
    5559    //////////////////////////////////////////////////////////////////////
    5660    // information about each serialized object saved
     
    143147
    144148    basic_oarchive_impl(unsigned int flags) :
    145149        m_flags(flags),
     150        m_cached_archive_caster(NULL),
     151        m_cached_archive_cast_pointer(NULL),
    146152        pending_object(NULL),
    147153        pending_bos(NULL)
    148154    {}
     
    454460basic_oarchive::end_preamble(){
    455461}
    456462
     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.
     466template<>
     467BOOST_ARCHIVE_DECL(void*)
     468archive_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
    457488} // namespace detail
    458489} // namespace archive
    459490} // 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  
    2020// explicitly instantiate for this type of text stream
    2121#include <boost/archive/impl/archive_pointer_iserializer.ipp>
    2222
     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
    2327namespace boost {
    2428namespace archive {
     29namespace detail {
    2530
    26 template class detail::archive_pointer_iserializer<polymorphic_iarchive> ;
     31template class archive_pointer_iserializer<polymorphic_iarchive> ;
     32template class archive_caster<polymorphic_iarchive, basic_iarchive> ;
    2733
     34} // namespace detail
    2835} // namespace serialization
    2936} // 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  
    2020// explicitly instantiate for this type of text stream
    2121#include <boost/archive/impl/archive_pointer_oserializer.ipp>
    2222
     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
    2327namespace boost {
    2428namespace archive {
     29namespace detail {
    2530
    26 template class detail::archive_pointer_oserializer<polymorphic_oarchive> ;
     31template class archive_pointer_oserializer<polymorphic_oarchive> ;
     32template class archive_caster<polymorphic_oarchive, basic_oarchive> ;
    2733
     34} // namespace detail
    2835} // namespace archive
    2936} // namespace boost