From 24b596bcf453dc9f1c5251e3b3c25fc12604a233 Mon Sep 17 00:00:00 2001 From: Robert Ramey Date: Sun, 2 Oct 2005 06:01:14 +0000 Subject: [PATCH] make sure no destructors call any virtual functions [SVN r31168] --- src/basic_iserializer.cpp | 2 +- src/basic_serializer_map.cpp | 10 ++- src/extended_type_info.cpp | 137 ++++++++++++++++++++--------- src/extended_type_info_no_rtti.cpp | 2 +- 4 files changed, 106 insertions(+), 45 deletions(-) diff --git a/src/basic_iserializer.cpp b/src/basic_iserializer.cpp index 8161dac6..95f8c2b9 100644 --- a/src/basic_iserializer.cpp +++ b/src/basic_iserializer.cpp @@ -17,7 +17,7 @@ namespace detail { BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer::basic_iserializer( - const boost::serialization::extended_type_info & eti + const boost::serialization::extended_type_info & eti ) : basic_serializer(eti), bpis(NULL) diff --git a/src/basic_serializer_map.cpp b/src/basic_serializer_map.cpp index 2aa96aca..5506aa79 100644 --- a/src/basic_serializer_map.cpp +++ b/src/basic_serializer_map.cpp @@ -33,7 +33,15 @@ type_info_pointer_compare::operator()( } BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) -basic_serializer_map::basic_serializer_map(){ +basic_serializer_map::basic_serializer_map(bool & deleted) : + m_deleted(deleted) +{ + m_deleted = false; +} + +BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_serializer_map::~basic_serializer_map(){ + m_deleted = true; } BOOST_ARCHIVE_DECL(bool) diff --git a/src/extended_type_info.cpp b/src/extended_type_info.cpp index bea6ce33..ad7db591 100644 --- a/src/extended_type_info.cpp +++ b/src/extended_type_info.cpp @@ -43,13 +43,20 @@ class tkmap { bool operator()(const extended_type_info * lhs, const extended_type_info * rhs) const { + assert(! lhs->is_destructing()); + assert(! rhs->is_destructing()); return *lhs < *rhs; } }; - typedef std::multiset type; - tkmap(){} +// typedef std::multiset type; + typedef std::set type; type m_map; static tkmap * m_self; + tkmap(){} + static tkmap::type::iterator + lookup(const extended_type_info * eti){ + return m_self->m_map.find(eti); + } public: ~tkmap(){ m_self = NULL; @@ -60,14 +67,16 @@ public: static tkmap instance; m_self = & instance; } + // make sure that attempt at registration is done only once + assert(lookup(eti) == m_self->m_map.end()); m_self->m_map.insert(eti); } static const extended_type_info * - find(const extended_type_info * t){ + find(const extended_type_info * eti){ if(NULL == m_self) return NULL; tkmap::type::const_iterator it; - it = m_self->m_map.find(t); + it = m_self->m_map.find(eti); if(it == m_self->m_map.end()) return NULL; return *it; @@ -76,6 +85,19 @@ public: purge(const extended_type_info * eti){ if(NULL == m_self) return; + // note: the following can't be used as this function + // is called from a destructor of extended_type_info. + // This will generate an error on some machines - which + // makes sense be cause by this time the derived class data + // might be gone. Leave this in as a reminder not to do this + #if 0 + tkmap::type::iterator it; + it = lookup(eti); + // it should be in there + assert(it != m_self->m_map.end()); + m_self->m_map.erase(it); + #endif + tkmap::type::iterator i = m_self->m_map.begin(); tkmap::type::iterator k = m_self->m_map.end(); while(i != k){ @@ -106,10 +128,32 @@ class ktmap { return std::strcmp(lhs->get_key(), rhs->get_key()) < 0; } }; - typedef std::multiset type; +// typedef std::multiset type; + typedef std::set type; type m_map; static ktmap * m_self; ktmap(){} + class extended_type_info_arg : public extended_type_info + { + public: + extended_type_info_arg(const char * key) : + extended_type_info(NULL) + { + m_key = key; + } + virtual bool + less_than(const extended_type_info &rhs) const + { + assert(false); + return false; // to prevent a syntax error + } + }; + static ktmap::type::iterator + lookup(const char *key){ + extended_type_info_arg arg(key); + return m_self->m_map.find(&arg); + } + public: ~ktmap(){ m_self = NULL; @@ -120,36 +164,10 @@ public: static ktmap instance; m_self = & instance; } + // make sure that all GUIDs are unique + assert(lookup(eti->get_key()) == m_self->m_map.end()); m_self->m_map.insert(eti); } - static void - purge(const extended_type_info * eti){ - if(NULL == m_self) - return; - ktmap::type::iterator i = m_self->m_map.begin(); - ktmap::type::iterator k = m_self->m_map.end(); - while(i != k){ - // note that the erase might invalidate i so save it here - ktmap::type::iterator j = i++; - if(*j == eti) - m_self->m_map.erase(j); - } - } - class extended_type_info_arg : public extended_type_info - { - public: - extended_type_info_arg(const char * search_key_) - : extended_type_info(NULL) - { - key = search_key_; - } - virtual bool - less_than(const extended_type_info &rhs) const - { - assert(false); - return false; // to prevent a syntax error - } - }; static const extended_type_info * find(const char *key) { @@ -162,7 +180,32 @@ public: return NULL; return *it; } + static void + purge(const extended_type_info * eti){ + if(NULL == m_self) + return; + // note: the following can't be used as this function + // is called from a destructor of extended_type_info. + // This will generate an error on some machines - which + // makes sense be cause by this time the derived class data + // might be gone. Leave this in as a reminder not to do this + #if 0 + ktmap::type::iterator it; + it = lookup(eti->get_key()); + // expect it to be in there ! + assert(it != m_self->m_map.end()); + m_self->m_map.erase(it); + #endif + ktmap::type::iterator i = m_self->m_map.begin(); + ktmap::type::iterator k = m_self->m_map.end(); + while(i != k){ + // note that the erase might invalidate i so save it here + ktmap::type::iterator j = i++; + if(*j == eti) + m_self->m_map.erase(j); + } + } }; ktmap * ktmap::m_self = NULL; @@ -179,43 +222,51 @@ BOOST_SERIALIZATION_DECL(void) extended_type_info::self_register() { detail::tkmap::insert(this); + m_self_registered = true; } BOOST_SERIALIZATION_DECL(void) extended_type_info::key_register(const char *key_) { if(NULL == key_) return; - key = key_; + m_key = key_; detail::ktmap::insert(this); + m_key_registered = true; } BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) -extended_type_info::extended_type_info(const char * type_info_key_) : - type_info_key(type_info_key_), - key(NULL) +extended_type_info::extended_type_info( + const char * type_info_key +) : + m_type_info_key(type_info_key), + m_self_registered(false), + m_key_registered(false), + m_is_destructing(false) {} BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) extended_type_info::~extended_type_info(){ // remove entries in maps which correspond to this type + m_is_destructing = true; BOOST_TRY{ - detail::tkmap::purge(this); - detail::ktmap::purge(this); + if(m_self_registered) + detail::tkmap::purge(this); + if(m_key_registered) + detail::ktmap::purge(this); unregister_void_casts(this); } BOOST_CATCH(...){} BOOST_CATCH_END } - BOOST_SERIALIZATION_DECL(int) extended_type_info::type_info_key_cmp(const extended_type_info & rhs) const { - if(type_info_key == rhs.type_info_key) + if(m_type_info_key == rhs.m_type_info_key) return 0; //return strcmp(lhs.type_info_key, rhs.type_info_key); // all we require is that the type_info_key be unique // so just compare the addresses - return type_info_key < rhs.type_info_key ? -1 : 1; + return m_type_info_key < rhs.m_type_info_key ? -1 : 1; } BOOST_SERIALIZATION_DECL(const extended_type_info *) @@ -231,6 +282,8 @@ extended_type_info::operator<(const extended_type_info &rhs) const { return true; if(i > 0) return false; + assert(! is_destructing()); + assert(! rhs.is_destructing()); return less_than(rhs); } diff --git a/src/extended_type_info_no_rtti.cpp b/src/extended_type_info_no_rtti.cpp index b4f9611f..a4947f79 100644 --- a/src/extended_type_info_no_rtti.cpp +++ b/src/extended_type_info_no_rtti.cpp @@ -26,7 +26,7 @@ BOOST_SERIALIZATION_DECL(bool) extended_type_info_no_rtti_0::less_than( const boost::serialization::extended_type_info &rhs) const { - return std::strcmp(key, rhs.get_key()) < 0; + return std::strcmp(m_key, rhs.get_key()) < 0; } BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())