diff --git a/src/basic_serializer_map.cpp b/src/basic_serializer_map.cpp index 4bd56407..a8b5688d 100644 --- a/src/basic_serializer_map.cpp +++ b/src/basic_serializer_map.cpp @@ -12,6 +12,12 @@ # pragma warning (disable : 4786) // too long name, harmless warning #endif +#include +#include + +#include +#include + #define BOOST_ARCHIVE_SOURCE #include #include @@ -23,52 +29,59 @@ namespace boost { namespace archive { namespace detail { -// note: We can't implement this as an associative -// container as such a container might be dependent -// upon the extended_type_info::m_key which might not -// be assigned until later. So we use a "slower" method. -// This not a big deal however as the slower "find" operations -// operations are only called occasionally: -// a) At module unloading -// b) Once per input archive - the value is cached in the archive -// implemenation. +bool +basic_serializer_map::type_info_pointer_compare::operator()( + const basic_serializer * lhs, const basic_serializer * rhs +) const { + return *lhs < *rhs; +} -BOOST_ARCHIVE_DECL(void) +BOOST_ARCHIVE_DECL(bool) basic_serializer_map::insert(const basic_serializer * bs){ - m_map.push_back(bs); + // attempt to insert serializer into it's map + const std::pair result = + m_map.insert(bs); + // if this fails, it's because it's been instantiated + // in multiple modules - DLLS - a recipe for problems. + // So trap this here + if(!result.second){ + boost::serialization::throw_exception( + archive_exception( + archive_exception::multiple_code_instantiation, + bs->get_debug_info() + ) + ); + } + return true; } BOOST_ARCHIVE_DECL(void) basic_serializer_map::erase(const basic_serializer * bs){ map_type::iterator it = m_map.begin(); map_type::iterator it_end = m_map.end(); - it = std::find(it, it_end, bs); - if(it != it_end){ - m_map.erase(it); + + while(it != it_end){ + // note item 9 from Effective STL !!! it++ + if(*it == bs) + m_map.erase(it++); + else + it++; } - else - assert(false); // this should never occur + // note: we can't do this since some of the eti records + // we're pointing to might be expired and the comparison + // won't work. Leave this as a reminder not to "optimize" this. + //it = m_map.find(bs); + //assert(it != m_map.end()); + //if(*it == bs) + // m_map.erase(it); } - -class equals { - const boost::serialization::extended_type_info * m_eti; -public: - bool operator()(const basic_serializer * bs) const { - return *m_eti == bs->get_eti(); - } - equals(const boost::serialization::extended_type_info * eti) : - m_eti(eti) - {} -}; - -// find the "oldest" matching pointer serializer BOOST_ARCHIVE_DECL(const basic_serializer *) basic_serializer_map::find( const boost::serialization::extended_type_info & eti ) const { - map_type::const_iterator it = m_map.begin(); - map_type::const_iterator it_end = m_map.end(); - it = std::find_if(it, it_end, equals(& eti)); + const basic_serializer_arg bs(eti); + map_type::const_iterator it; + it = m_map.find(& bs); assert(it != m_map.end()); return *it; } diff --git a/src/extended_type_info.cpp b/src/extended_type_info.cpp index abe876d8..47e20c5f 100644 --- a/src/extended_type_info.cpp +++ b/src/extended_type_info.cpp @@ -75,6 +75,9 @@ class extended_type_info_arg : public extended_type_info assert(false); return false; }; + virtual const char * get_debug_info() const { + return get_key(); + } public: extended_type_info_arg(const char * key) : extended_type_info(0, key) diff --git a/src/void_cast.cpp b/src/void_cast.cpp index 5f324aa9..93f90b94 100644 --- a/src/void_cast.cpp +++ b/src/void_cast.cpp @@ -15,6 +15,9 @@ #include #include // NULL +#ifdef BOOST_SERIALIZATION_LOG +#include +#endif // STL #include @@ -190,6 +193,14 @@ void_caster::recursive_register(bool includes_virtual_base) const { void_cast_detail::set_type & s = void_cast_detail::void_caster_registry::get_mutable_instance(); + #ifdef BOOST_SERIALIZATION_LOG + std::clog << "recursive_register\n"; + std::clog << m_derived->get_debug_info(); + std::clog << "<-"; + std::clog << m_base->get_debug_info(); + std::clog << "\n"; + #endif + s.insert(this); // generate all implied void_casts. diff --git a/test/test_exported.cpp b/test/test_exported.cpp index 374790b9..5dfc9849 100644 --- a/test/test_exported.cpp +++ b/test/test_exported.cpp @@ -24,12 +24,15 @@ namespace std{ #include #include +#include + #include #include "test_tools.hpp" #include "polymorphic_base.hpp" -class polymorphic_derived1 : public polymorphic_base +class polymorphic_derived1 : + public polymorphic_base { friend class boost::serialization::access; template diff --git a/test/test_simple_class_ptr.cpp b/test/test_simple_class_ptr.cpp index dd469032..721b3259 100644 --- a/test/test_simple_class_ptr.cpp +++ b/test/test_simple_class_ptr.cpp @@ -30,7 +30,7 @@ int test_main( int /* argc */, char* /* argv */[] ) BOOST_REQUIRE(NULL != testfile); - A *ta = new A(); + const A *ta = new A(); A *ta1 = NULL; { diff --git a/vc7ide/Library.vcproj b/vc7ide/Library.vcproj index f00c61d8..36e74283 100644 --- a/vc7ide/Library.vcproj +++ b/vc7ide/Library.vcproj @@ -394,6 +394,9 @@ + + @@ -614,6 +617,9 @@ + + @@ -678,9 +684,6 @@ - - @@ -770,9 +773,6 @@ - -