$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: ramey_at_[hidden]
Date: 2007-10-29 15:47:01
Author: ramey
Date: 2007-10-29 15:47:00 EDT (Mon, 29 Oct 2007)
New Revision: 40561
URL: http://svn.boost.org/trac/boost/changeset/40561
Log:
First implementation of thread safe lock free serialization
Text files modified: 
   branches/serialization_next_release/boost/libs/serialization/src/basic_archive.cpp             |     2                                         
   branches/serialization_next_release/boost/libs/serialization/src/basic_iserializer.cpp         |     2                                         
   branches/serialization_next_release/boost/libs/serialization/src/basic_oserializer.cpp         |     2                                         
   branches/serialization_next_release/boost/libs/serialization/src/basic_serializer_map.cpp      |    59 ++--                                    
   branches/serialization_next_release/boost/libs/serialization/src/extended_type_info.cpp        |   187 ++++------------                        
   branches/serialization_next_release/boost/libs/serialization/src/extended_type_info_typeid.cpp |   150 +++---------                            
   branches/serialization_next_release/boost/libs/serialization/src/void_cast.cpp                 |   452 +++++++++++++-------------------------- 
   7 files changed, 276 insertions(+), 578 deletions(-)
Modified: branches/serialization_next_release/boost/libs/serialization/src/basic_archive.cpp
==============================================================================
--- branches/serialization_next_release/boost/libs/serialization/src/basic_archive.cpp	(original)
+++ branches/serialization_next_release/boost/libs/serialization/src/basic_archive.cpp	2007-10-29 15:47:00 EDT (Mon, 29 Oct 2007)
@@ -17,7 +17,7 @@
 //      [
 //          exported key - class name*
 //          tracking level - always/never
-//          file version
+//          class version
 //      ]
 //
 //      if tracking
Modified: branches/serialization_next_release/boost/libs/serialization/src/basic_iserializer.cpp
==============================================================================
--- branches/serialization_next_release/boost/libs/serialization/src/basic_iserializer.cpp	(original)
+++ branches/serialization_next_release/boost/libs/serialization/src/basic_iserializer.cpp	2007-10-29 15:47:00 EDT (Mon, 29 Oct 2007)
@@ -20,7 +20,7 @@
     const boost::serialization::extended_type_info & eti
 ) :
     basic_serializer(eti), 
-    bpis(NULL)
+    m_bpis(NULL)
 {}
 
 BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
Modified: branches/serialization_next_release/boost/libs/serialization/src/basic_oserializer.cpp
==============================================================================
--- branches/serialization_next_release/boost/libs/serialization/src/basic_oserializer.cpp	(original)
+++ branches/serialization_next_release/boost/libs/serialization/src/basic_oserializer.cpp	2007-10-29 15:47:00 EDT (Mon, 29 Oct 2007)
@@ -20,7 +20,7 @@
         const boost::serialization::extended_type_info & eti
 ) :
     basic_serializer(eti), 
-    bpos(NULL)
+    m_bpos(NULL)
 {}
 
 BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
Modified: branches/serialization_next_release/boost/libs/serialization/src/basic_serializer_map.cpp
==============================================================================
--- branches/serialization_next_release/boost/libs/serialization/src/basic_serializer_map.cpp	(original)
+++ branches/serialization_next_release/boost/libs/serialization/src/basic_serializer_map.cpp	2007-10-29 15:47:00 EDT (Mon, 29 Oct 2007)
@@ -14,8 +14,6 @@
 
 #include <stdlib.h> // for NULL
 
-#include <set>
-
 #define BOOST_ARCHIVE_SOURCE
 #include <boost/archive/detail/basic_serializer.hpp>
 #include <boost/archive/detail/basic_serializer_map.hpp>
@@ -27,6 +25,7 @@
 namespace archive {
 namespace detail {
 
+#if 0
 BOOST_ARCHIVE_DECL(bool) 
 type_info_pointer_compare::operator()(
     const basic_serializer * lhs, const basic_serializer * rhs
@@ -34,6 +33,19 @@
     return *lhs < *rhs;
 }
 
+class basic_serializer_arg : public basic_serializer {
+public:
+    basic_serializer_arg(const serialization::extended_type_info & eti) :
+        basic_serializer(eti)
+    {}
+};
+#endif
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#if 0
 BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
 basic_serializer_map::basic_serializer_map(bool & deleted) :
     m_deleted(deleted)
@@ -41,6 +53,19 @@
     m_deleted = false;
 }
 
+BOOST_ARCHIVE_DECL(const basic_serializer *) 
+basic_serializer_map::tfind(
+    const boost::serialization::extended_type_info & eti
+) const {
+    const basic_serializer_arg bs(eti);
+    map_type::const_iterator it;
+    boost::serialization::singleton<basic_serializer_map>::lease l;
+    it = l->m_map.find(& bs);
+    if(it == l->m_map.end())
+        return NULL;
+    return *it;
+}
+
 BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
 basic_serializer_map::~basic_serializer_map(){
     m_deleted = true;
@@ -48,33 +73,13 @@
 
 BOOST_ARCHIVE_DECL(bool) 
 basic_serializer_map::insert(const basic_serializer * bs){
-    return m_map.insert(bs).second;
+    boost::serialization::singleton<basic_serializer_map>::lease l;
+    return l->m_map.insert(bs).second;
 }
 
 BOOST_ARCHIVE_DECL(void) 
 basic_serializer_map::erase(basic_serializer * bs){
-    m_map.erase(bs);
+    boost::serialization::singleton<basic_serializer_map>::lease l;
+    l->m_map.erase(bs);
 }
-
-class basic_serializer_arg : public basic_serializer {
-public:
-    basic_serializer_arg(const serialization::extended_type_info & eti) :
-        basic_serializer(eti)
-    {}
-};
-
-BOOST_ARCHIVE_DECL(const basic_serializer *) 
-basic_serializer_map::tfind(
-    const boost::serialization::extended_type_info & eti
-) const {
-    const basic_serializer_arg bs(eti);
-    map_type::const_iterator it;
-    it = m_map.find(& bs);
-    if(it == m_map.end())
-        return NULL;
-    return *it;
-}
-
-} // namespace detail
-} // namespace archive
-} // namespace boost
+#endif
Modified: branches/serialization_next_release/boost/libs/serialization/src/extended_type_info.cpp
==============================================================================
--- branches/serialization_next_release/boost/libs/serialization/src/extended_type_info.cpp	(original)
+++ branches/serialization_next_release/boost/libs/serialization/src/extended_type_info.cpp	2007-10-29 15:47:00 EDT (Mon, 29 Oct 2007)
@@ -14,6 +14,7 @@
 
 #include <algorithm>
 #include <set>
+#include <utility>
 #include <cassert>
 
 #include <boost/config.hpp> // msvc needs this to suppress warning
@@ -24,7 +25,8 @@
 #endif
 
 #include <boost/detail/no_exceptions_support.hpp>
-#include <boost/detail/lightweight_mutex.hpp>
+#include <boost/serialization/singleton.hpp>
+#include <boost/serialization/force_include.hpp>
 
 #define BOOST_SERIALIZATION_SOURCE
 #include <boost/serialization/extended_type_info.hpp>
@@ -33,147 +35,75 @@
 namespace serialization {
 namespace detail {
 
-// map for finding the unique global extended type info entry given its GUID
-class ktmap {
-    struct key_compare
-    {
-        bool
-        operator()(
-            const extended_type_info * lhs, 
-            const extended_type_info * rhs
-        ) const {
-            return *lhs < *rhs;
-        }
-    };
-    // the reason that we use multiset rather than set is that its possible
-    // that multiple eti records will be created as DLLS that use the same
-    // eti are loaded.  Using a multset will automatically keep track of the
-    // times this occurs so that when the last dll is unloaded, the type will
-    // become "unregistered"
-    typedef std::multiset<const extended_type_info *, key_compare> type;
-    type m_map;
-    class extended_type_info_arg : public extended_type_info
-    {
-    public:
-        extended_type_info_arg(const char * key){
-            m_key = key;
-        }
-        ~extended_type_info_arg(){
-            m_key = NULL;
-        }
-    };
-public:
-    void
-    insert(const extended_type_info * eti){
-        m_map.insert(eti);
-    }
-    const extended_type_info * 
-    find(const char *key)
-    {
-        const extended_type_info_arg eti(key);
-        ktmap::type::iterator it;
-        it = m_map.find(& eti);
-        if(it == m_map.end())
-            return NULL;
-        return *it;
-    }
-    void 
-    purge(const extended_type_info * eti){
-        ktmap::type::iterator it;
-        it = m_map.find(eti);
-        // expect it to be in there ! but check anyway !
-        if(it != m_map.end())
-            m_map.erase(it);
+struct key_compare
+{
+    bool
+    operator()(
+        const extended_type_info * lhs, 
+        const extended_type_info * rhs
+    ) const {
+        return *lhs < *rhs;
     }
 };
+typedef std::set<
+    const extended_type_info *, 
+    key_compare
+> ktmap;
 
-// the above structer is fine - except for:
-//     - its not thread-safe
-//     - it doesn't support the necessary initialization
-//       to be a singleton.
-//
-// Here we add the sauce to address this
-
-class safe_ktmap {
-    // this addresses a problem.  Our usage patter for a typical case is:
-    // extended_type_info
-    // key_register
-    //     ktmap
-    //     insert item
-    // ...
-    // ~extended_type_info
-    //     purge item
-    //  ~ktmap
-    //  ~extended_type_info // crash!! ktmap already deleted
-    safe_ktmap(){
-        ++count;
-    }
-    ~safe_ktmap(){
-        --count;
-    }
-    static short int count;
+template ktmap;
 
-    static boost::detail::lightweight_mutex &
-    get_mutex(){
-        static boost::detail::lightweight_mutex m;
-        return m;
-    }
-    static ktmap & get_instance(){
-        static ktmap m;
-        return m;
-    }
+class extended_type_info_arg : public extended_type_info
+{
 public:
-    static void
-    insert(const extended_type_info * eti){
-        boost::detail::lightweight_mutex::scoped_lock sl(get_mutex());
-        get_instance().insert(eti);
-    }
-    static const extended_type_info * 
-    find(const char *key){
-        boost::detail::lightweight_mutex::scoped_lock sl(get_mutex());
-        return get_instance().find(key);
+    extended_type_info_arg(const char * key){
+        m_key = key;
     }
-    static void 
-    purge(const extended_type_info * eti){
-        if(0 == detail::safe_ktmap::count)
-            return;
-        boost::detail::lightweight_mutex::scoped_lock sl(get_mutex());
-        get_instance().purge(eti);
+    ~extended_type_info_arg(){
+        m_key = NULL;
     }
 };
 
-short int safe_ktmap::count = 0;
-
 } // namespace detail
 
-BOOST_SERIALIZATION_DECL(const extended_type_info *) 
-extended_type_info::find(const char *key)
-{
-    return detail::safe_ktmap::find(key);
+BOOST_SERIALIZATION_DECL(void)  
+extended_type_info::key_register(const char *key) {
+    assert(NULL != key);
+    m_key = key;
+    std::pair<detail::ktmap::const_iterator, bool> result;
+    // prohibit duplicates and multiple registrations
+    result = singleton<detail::ktmap>::get_mutable_instance().insert(this);
+    assert(result.second);
+    // would like to throw and exception here but I don't
+    // have one conveniently defined
+    // throw(?)
 }
 
-BOOST_SERIALIZATION_DECL(void)  
-extended_type_info::key_register(const char *k) {
-    assert(NULL != k);
-    m_key = k;
-    detail::safe_ktmap::insert(this);
+BOOST_SERIALIZATION_DECL(const extended_type_info *) 
+extended_type_info::find(const char *key) {
+    const detail::ktmap & k = singleton<detail::ktmap>::get_const_instance();
+    const detail::extended_type_info_arg eti_key(key);
+    const detail::ktmap::const_iterator it = k.find(& eti_key);
+    if(k.end() == it)
+        return NULL;
+    return *(it);
 }
 
 extended_type_info::extended_type_info() : 
     m_key(NULL)
 {
+    // make sure that the ktmap is instantiated before 
+    // the first key is added to it.
+    singleton<detail::ktmap>::get_const_instance();
 }
 
 BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) 
 extended_type_info::~extended_type_info(){
-    if(NULL == m_key)
-        return;
-    // remove entries in maps which correspond to this type
-    BOOST_TRY{
-        detail::safe_ktmap::purge(this);
+    if(NULL != m_key){
+        unsigned int erase_count;
+        erase_count = 
+            singleton<detail::ktmap>::get_mutable_instance().erase(this);
+        assert(1 == erase_count);
     }
-    BOOST_CATCH(...){}
-    BOOST_CATCH_END
 }
 
 BOOST_SERIALIZATION_DECL(bool)  
@@ -181,25 +111,10 @@
     const extended_type_info & lhs, 
     const extended_type_info & rhs
 ){
-    if(& lhs == & rhs)
-        return true;
-    const char * l = lhs.get_key();
-    const char * r = rhs.get_key();
-    // neither have been exported
-    if(NULL == l && NULL == r)
-        // then the above test is definitive
-        return false;
-    // shortcut to exploit string pooling
-    if(l == r)
-        return true;
-    if(NULL == r)
-        return false;
-    if(NULL == l)
-        return false;
-    return 0 == std::strcmp(l, r); 
+    return (& lhs == & rhs);
 }
 
-BOOST_SERIALIZATION_DECL(bool)  
+BOOST_SERIALIZATION_DECL(bool)
 operator<(
     const extended_type_info & lhs, 
     const extended_type_info & rhs
Modified: branches/serialization_next_release/boost/libs/serialization/src/extended_type_info_typeid.cpp
==============================================================================
--- branches/serialization_next_release/boost/libs/serialization/src/extended_type_info_typeid.cpp	(original)
+++ branches/serialization_next_release/boost/libs/serialization/src/extended_type_info_typeid.cpp	2007-10-29 15:47:00 EDT (Mon, 29 Oct 2007)
@@ -15,7 +15,8 @@
 #include <typeinfo>
 
 #include <boost/detail/no_exceptions_support.hpp>
-#include <boost/detail/lightweight_mutex.hpp>
+
+#include <boost/serialization/singleton.hpp>
 
 #define BOOST_SERIALIZATION_SOURCE
 #include <boost/serialization/extended_type_info_typeid.hpp>
@@ -24,121 +25,45 @@
 namespace serialization { 
 namespace detail {
 
-// map for finding the unique global extended type entry for a given type
-class tkmap {
-    struct type_compare
-    {
-        bool
-        operator()(
-            const extended_type_info_typeid_0 * lhs,
-            const extended_type_info_typeid_0 * rhs
-        ) const {
-            const std::type_info & l = lhs->get_typeid();
-            const std::type_info & r = rhs->get_typeid();
-            return l.before(r);
-        }
-    };
-    // the reason that we use multiset rather than set is that its possible
-    // that multiple eti records will be created as DLLS that use the same
-    // eti are loaded.  Using a multset will automatically keep track of the
-    // times this occurs so that when the last dll is unloaded, the type will
-    // become "unregistered"
-    typedef std::multiset<
-        const extended_type_info_typeid_0 *,
-        type_compare
-    > type;
-    
-    type m_map;
-
-public:
-    void
-    insert(const extended_type_info_typeid_0 * eti){
-        m_map.insert(eti);
-    }
-    const extended_type_info_typeid_0 * 
-    find(const extended_type_info_typeid_0 * eti){
-        tkmap::type::const_iterator it;
-        it = m_map.find(eti);
-        if(it == m_map.end())
-            return NULL;
-        return *it;
-    }
-    void 
-    purge(const extended_type_info_typeid_0 * eti){
-        tkmap::type::iterator it;
-        it = m_map.find(eti);
-        if(it != m_map.end())
-            m_map.erase(it);
-    }
-};
-
-class safe_tkmap {
-    // this addresses a problem.  Our usage patter for a typical case is:
-    // extended_type_info_typeid
-    // type_register
-    //     tkmap
-    //     insert item
-    // ...
-    // ~extended_type_info_typeid
-    //     purge item
-    //  tkmap
-    //  ~extended_type_info_typeid // crash!! tkmap already deleted
-    safe_tkmap(){
-        ++count;
-    }
-    ~safe_tkmap(){
-        --count;
-    }
-    static short int count;
-
-    static boost::detail::lightweight_mutex &
-    get_mutex(){
-        static boost::detail::lightweight_mutex m;
-        return m;
-    }
-    static tkmap & get_instance(){
-        static tkmap m;
-        return m;
-    }
-public:
-    static void
-    insert(const extended_type_info_typeid_0 * eti){
-        boost::detail::lightweight_mutex::scoped_lock sl(get_mutex());
-        get_instance().insert(eti);
-    }
-    static const extended_type_info_typeid_0 * 
-    find(const extended_type_info_typeid_0 * eti){
-        boost::detail::lightweight_mutex::scoped_lock sl(get_mutex());
-        return get_instance().find(eti);
-    }
-    static void 
-    purge(const extended_type_info_typeid_0 * eti){
-        if(0 == count)
-            return;
-        boost::detail::lightweight_mutex::scoped_lock sl(get_mutex());
-        get_instance().purge(eti);
+struct type_compare
+{
+    bool
+    operator()(
+        const extended_type_info_typeid_0 * lhs,
+        const extended_type_info_typeid_0 * rhs
+    ) const {
+        const std::type_info & l = lhs->get_typeid();
+        const std::type_info & r = rhs->get_typeid();
+        return l.before(r);
     }
 };
+typedef std::set<
+    const extended_type_info_typeid_0 *,
+    type_compare
+> tkmap;
+    
+template tkmap;
 
-short int safe_tkmap::count = 0;
+BOOST_SERIALIZATION_DECL(void) 
+extended_type_info_typeid_0::type_register(const std::type_info & ti){
+    m_ti = & ti;
+    std::pair<tkmap::const_iterator, bool> result;
+    result = singleton<tkmap>::get_mutable_instance().insert(this);
+    assert(result.second);
+    // would like to throw and exception here but I don't
+    // have one conveniently defined
+    // throw(?)
+}
 
 BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) 
 extended_type_info_typeid_0::~extended_type_info_typeid_0()
 {
-    if(NULL == m_ti)
-        return;
-    // remove entries in maps which correspond to this type
-    BOOST_TRY{
-        detail::safe_tkmap::purge(this);
+    if(NULL != m_ti){
+        // remove entries in maps which correspond to this type
+        unsigned int erase_count;
+        erase_count 
+            = singleton<tkmap>::get_mutable_instance().erase(this);
     }
-    BOOST_CATCH(...){}
-    BOOST_CATCH_END
-}
-
-BOOST_SERIALIZATION_DECL(void) 
-extended_type_info_typeid_0::type_register(const std::type_info & ti){
-    m_ti = & ti;
-    detail::safe_tkmap::insert(this);
 }
 
 // this derivation is used for creating search arguments
@@ -146,8 +71,7 @@
     public extended_type_info_typeid_0
 {
 public:
-    extended_type_info_typeid_arg(const std::type_info & ti)
-    { 
+    extended_type_info_typeid_arg(const std::type_info & ti){ 
         // note absense of self register and key as this is used only as
         // search argument given a type_info reference and is not to 
         // be added to the map.
@@ -163,7 +87,11 @@
     const std::type_info & ti
 ){
     detail::extended_type_info_typeid_arg etia(ti);
-    return safe_tkmap::find(& etia);
+    const tkmap & t = singleton<tkmap>::get_const_instance();
+    const tkmap::const_iterator it = t.find(& etia);
+    if(t.end() == it)
+        return NULL;
+    return *(it);
 }
 
 } // namespace detail
Modified: branches/serialization_next_release/boost/libs/serialization/src/void_cast.cpp
==============================================================================
--- branches/serialization_next_release/boost/libs/serialization/src/void_cast.cpp	(original)
+++ branches/serialization_next_release/boost/libs/serialization/src/void_cast.cpp	2007-10-29 15:47:00 EDT (Mon, 29 Oct 2007)
@@ -8,7 +8,7 @@
 // <gennadiy.rozental_at_[hidden]>
 
 //  See http://www.boost.org for updates, documentation, and revision history.
- 
+
 #if (defined _MSC_VER) && (_MSC_VER == 1200)
 # pragma warning (disable : 4786) // too long name, harmless warning
 #endif
@@ -22,41 +22,82 @@
 #include <cassert>
 
 // BOOST
-#include <boost/detail/lightweight_mutex.hpp>
-
-#define BOOST_SERIALIZATION_SOURCE
+#include <boost/serialization/singleton.hpp>
 #include <boost/serialization/extended_type_info.hpp>
+#define BOOST_SERIALIZATION_SOURCE
 #include <boost/serialization/void_cast.hpp>
 
 namespace boost { 
 namespace serialization {
 namespace void_cast_detail {
 
-// just used as a search key
-class void_caster_argument : public void_caster
+// registry of casting objects
+struct void_caster_compare
 {
-    virtual void const*
-    upcast( void const* t ) const {
-        assert(false);
-        return NULL;
-    }
-    virtual void const*
-    downcast( void const* t ) const {
-        assert(false);
-        return NULL;
+    bool
+    operator()(
+        const void_caster * lhs, 
+        const void_caster * rhs 
+    ) const {
+        if( lhs->m_derived < rhs->m_derived )
+            return true;
+        if( rhs->m_derived < lhs->m_derived)
+            return false;   
+        if( lhs->m_base < rhs->m_base )
+            return true;
+        return false;
     }
-public:
-    void_caster_argument(
-        extended_type_info const& derived_type_,
-        extended_type_info const& base_type_
-    ) :
-        void_caster(derived_type_, base_type_)
-    {}
 };
 
-//////////////////////////////////////////////////////
-// void_caster implementation for indirect inheritance
+typedef std::set<const void_caster *, void_caster_compare> set_type;
+typedef boost::serialization::singleton<set_type> void_caster_registry;
+
+template void_caster_registry;
 
+// implementation of void caster base class
+BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
+void_caster::void_caster(
+    extended_type_info const & derived,
+    extended_type_info const & base 
+) :
+    m_derived(derived),
+    m_base(base)
+{}
+
+void
+void_caster::static_register() const {
+    void_caster_registry::get_mutable_instance().insert(this);
+    // to do - add new void_caster_derived entries
+    // which can be generated by adding this new primitive
+    /*
+    while(){
+        if(!extend_down(this)
+        && !extend_up(this))
+            break;
+    }
+    */
+}
+
+void
+void_caster::static_unregister() const {
+    void_cast_detail::set_type & st 
+        = void_caster_registry::get_mutable_instance();
+    void_cast_detail::set_type::iterator it;
+    it = st.find(this);
+    assert(st.end() != it);
+    st.erase(it);
+    // to do - remove all void_caster_derived entries
+    // which depend upon this primitive
+    /*
+    while(){
+        if(!truncate_down(this)
+        && !truncate_up(this))
+            break;
+    }
+    */
+}
+
+// implementation of shortcut void caster
 class void_caster_derived : public void_caster
 {
     std::ptrdiff_t difference;
@@ -70,325 +111,134 @@
     }
 public:
     void_caster_derived(
-        extended_type_info const& derived_type_,
-        extended_type_info const& base_type_,
-        std::ptrdiff_t difference_
+        const extended_type_info & derived,
+        const extended_type_info & base,
+        std::ptrdiff_t difference
     ) :
-        void_caster(derived_type_, base_type_),
-        difference( difference_ )
-    {}
+        void_caster(derived, base),
+        difference( difference )
+    {
+        this->static_register();
+    }
+    ~void_caster_derived(){
+        this->static_unregister();
+    }
 };
 
-////////////////////////////////////////////////////////////
-// registry to hold all casters for all base/derived pairs
-// used.
-
-class void_caster_registry
+// just used as a search key
+class void_caster_argument : public void_caster
 {
-    struct void_caster_compare
-    {
-        bool
-        operator()(
-            const void_caster * lhs, 
-            const void_caster * rhs 
-        ) const {
-            return *lhs < *rhs;
-        }
-    };
-    // note usage of multi-set since it's possible that dynamically
-    // loaded libraries might create multiple instances of a given
-    // instance of a void caster.  This implements automatic counting
-    typedef std::multiset<const void_caster *, void_caster_compare> set_type;
-    set_type m_set;
+    virtual void const*
+    upcast( void const* t ) const {
+        assert(false);
+        return NULL;
+    }
+    virtual void const*
+    downcast( void const* t ) const {
+        assert(false);
+        return NULL;
+    }
 public:
-    typedef set_type::iterator iterator;
-    typedef set_type::const_iterator const_iterator;
-    void
-    insert(const void_caster * vcp){
-        m_set.insert(vcp);
-    }
-    void
-    purge(const void_caster * vcp){
-        iterator it = m_set.find(vcp);
-        // expect it to be in there ! but check anyway !
-        assert(it != m_set.end());
-        m_set.erase(it);
-    }
-    void const *
-    upcast(
-        extended_type_info const & derived_type,
-        extended_type_info const & base_type,
-        void const * const t,
-        bool top
-    );
-    void const *
-    downcast(
-        const extended_type_info & derived_type,
-        const extended_type_info & base_type,
-        const void * const t,
-        bool top
-    );
+    void_caster_argument(
+        const extended_type_info & derived,
+        const extended_type_info & base
+    ) :
+        void_caster(derived, base)
+    {}
+    ~void_caster_argument(){};
 };
 
-inline void const *
-void_caster_registry::upcast(
-    extended_type_info const & derived_type,
-    extended_type_info const & base_type,
-    void const * const t,
-    bool top
+} // namespace void_cast_detail
+
+// Given a void *, assume that it really points to an instance of one type
+// and alter it so that it would point to an instance of a related type.
+// Return the altered pointer. If there exists no sequence of casts that
+// can transform from_type to to_type, return a NULL.  
+BOOST_SERIALIZATION_DECL(void const *)  
+void_upcast(
+    const extended_type_info & derived,
+    const extended_type_info & base,
+    const void * t
 ){
     // same types - trivial case
-    if (derived_type == base_type)
+    if (derived == base)
         return t;
-    
+
     // check to see if base/derived pair is found in the registry
-    void_caster_argument ca(derived_type, base_type );
-    const_iterator it;
-    it = m_set.find( &ca );
-    
-    const void * t_new = NULL;
+    const void_cast_detail::set_type & s
+        = void_cast_detail::void_caster_registry::get_const_instance();
+    void_cast_detail::set_type::const_iterator it;
+    void_cast_detail::void_caster_argument ca(derived, base);
 
+    it = s.find(& ca);
+    
     // if so
-    if (it != m_set.end())
+    if (s.end() != it)
         // we're done
         return (*it)->upcast(t);
 
     // try to find a chain that gives us what we want
-    for(
-        it = m_set.begin();
-        it != m_set.end();
-        ++it
-    ){
+    for(it = s.begin(); it != s.end(); ++it){
         // if the current candidate doesn't cast to the desired target type
-        if ((*it)->m_base_type == base_type){
+        if((*it)->m_base == base){
             // if the current candidate casts from the desired source type
-            if ((*it)->m_derived_type == derived_type){
+            if ((*it)->m_derived == derived){
                 // we have a base/derived match - we're done
                 // cast to the intermediate type
-                t_new = (*it)->upcast(t);
-                break;
-            }
-            t_new = void_upcast(derived_type, (*it)->m_derived_type, t, false);
-            if (NULL != t_new){
-                t_new = (*it)->upcast(t_new);
-                assert(NULL != t_new);
-                if(top){
-                    // register the this pair so we will have to go through
-                    // keep this expensive search process more than once.
-                    const void_caster * vcp = 
-                        new void_caster_derived( 
-                            derived_type,
-                            base_type,
-                            static_cast<const char*>(t_new) - static_cast<const char*>(t)
-                        );
-                    m_set.insert(vcp);
-                }
-                break;
+                return (*it)->upcast(t);
             }
+            const void * t_new;
+            t_new = void_upcast(derived, (*it)->m_derived, t);
+            if(NULL != t_new)
+                return (*it)->upcast(t_new);
         }
     }
-    return t_new;
+    return NULL;
 }
 
-inline void const *
-void_caster_registry::downcast(
-    const extended_type_info & derived_type,
-    const extended_type_info & base_type,
-    const void * const t,
-    bool top
+BOOST_SERIALIZATION_DECL(void const *)  
+void_downcast(
+    extended_type_info const & derived,
+    extended_type_info const & base,
+    const void * const t
 ){
     // same types - trivial case
-    if (derived_type == base_type)
+    if (derived == base)
         return t;
-    
+
     // check to see if base/derived pair is found in the registry
-    void_caster_argument ca(derived_type, base_type );
-    const_iterator it;
-    it = m_set.find( &ca );
+    const void_cast_detail::set_type & s
+        = void_cast_detail::void_caster_registry::get_const_instance();
+    void_cast_detail::set_type::const_iterator it;
+    void_cast_detail::void_caster_argument ca(derived, base);
+
+    it = s.find(& ca);
     
     // if so
-    if (it != m_set.end())
+    if (s.end() != it)
         // we're done
-        return (*it)->downcast(t);
+        return(*it)->downcast(t);
 
-    const void * t_new = NULL;
     // try to find a chain that gives us what we want
-    for(
-        it = m_set.begin();
-        it != m_set.end();
-        ++it
-    ){
-        // if the current candidate doesn't casts from the desired target type
-        if ((*it)->m_derived_type == derived_type){
-            // if the current candidate casts to the desired source type
-            if ((*it)->m_base_type == base_type){
+    for(it = s.begin(); it != s.end(); ++it){
+        // if the current candidate doesn't cast to the desired target type
+        if ((*it)->m_derived == derived){
+            // if the current candidate casts from the desired source type
+            if ((*it)->m_base == base){
                 // we have a base/derived match - we're done
                 // cast to the intermediate type
-                t_new = (*it)->downcast(t);
-                break;
-            }
-            t_new = void_downcast((*it)->m_base_type, base_type, t, false);
-            if (NULL != t_new){
-                t_new = (*it)->downcast(t_new);
-                assert(NULL != t_new);
-                if(top){
-                    // register the this pair so we will have to go through
-                    // keep this expensive search process more than once.
-                    const void_caster * vcp = 
-                        new void_caster_derived( 
-                            derived_type,
-                            base_type,
-                            static_cast<const char*>(t) - static_cast<const char*>(t_new)
-                        );
-                    m_set.insert(vcp);
-                }
-                break;
+                return (*it)->downcast(t);
             }
+            const void * t_new;
+            t_new = void_downcast((*it)->m_base, base, t);
+            if(NULL != t_new)
+                return (*it)->downcast(t_new);
         }
     }
-    return t_new;
-}
-
-// the above structer is fine - except for:
-//     - its not thread-safe
-//     - it doesn't support the necessary initialization
-//       to be a singleton.
-//
-// Here we add the sauce to address this
-
-class safe_void_caster_registry {
-    // this addresses a problem.  Our usage patter for a typical case is:
-    // void_caster
-    // void_caster_register
-    //     void_caster_registry
-    //     insert item
-    // ...
-    // ~void_caster
-    //     purge item
-    //  ~void_caster_registry
-    //  ~void_caster // crash!! void_caster_registry already deleted
-    safe_void_caster_registry (){
-        ++count;
-    }
-    ~safe_void_caster_registry (){
-        --count;
-    }
-    static short int count;
-
-    static boost::detail::lightweight_mutex &
-    get_mutex(){
-        static boost::detail::lightweight_mutex m;
-        return m;
-    }
-    static void_caster_registry & get_instance(){
-        static void_caster_registry m;
-        return m;
-    }
-public:
-    static void
-    insert(const void_caster * vcp){
-        boost::detail::lightweight_mutex::scoped_lock sl(get_mutex());
-        get_instance().insert(vcp);
-    }
-    static void const *
-    upcast(
-        extended_type_info const & derived_type,
-        extended_type_info const & base_type,
-        void const * const t,
-        bool top
-    ){
-        boost::detail::lightweight_mutex::scoped_lock sl(get_mutex());
-        return get_instance().upcast(derived_type, base_type, t, top);
-    }
-    static void const *
-    downcast(
-        const extended_type_info & derived_type,
-        const extended_type_info & base_type,
-        const void * const t,
-        bool top
-    ){
-        boost::detail::lightweight_mutex::scoped_lock sl(get_mutex());
-        return get_instance().downcast(derived_type, base_type, t, top);
-    }
-    static void
-    purge(const void_caster * vcp){
-        boost::detail::lightweight_mutex::scoped_lock sl(get_mutex());
-        if(count == 0)
-            return;
-        get_instance().purge(vcp);
-    }
-};
-
-short int safe_void_caster_registry::count = 0;
-
-////////////////////////////////////////////////
-// void_caster implementation
-
-BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
-void_caster::void_caster(
-    extended_type_info const & derived_type_,
-    extended_type_info const & base_type_ 
-) :
-    m_derived_type( derived_type_),
-    m_base_type(base_type_)
-{}
-
-BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
-void_caster::~void_caster(){
-    safe_void_caster_registry::purge(this);
-}
-
-void BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
-void_caster::static_register(const void_caster * vcp) 
-{
-    safe_void_caster_registry::insert(vcp);
-}
-
-BOOST_SERIALIZATION_DECL(bool)
-operator<(const void_caster & lhs, const void_caster & rhs){
-    if( lhs.m_derived_type < rhs.m_derived_type )
-        return true;
-
-    if( rhs.m_derived_type < lhs.m_derived_type)
-        return false;
-
-    if( lhs.m_base_type < rhs.m_base_type )
-        return true;
-
-    return false;
-}
-
-} // namespace void_cast_detail
-
-// Given a void *, assume that it really points to an instance of one type
-// and alter it so that it would point to an instance of a related type.
-// Return the altered pointer. If there exists no sequence of casts that
-// can transform from_type to to_type, return a NULL.  
-
-BOOST_SERIALIZATION_DECL(void const *)
-void_upcast(
-    extended_type_info const & derived_type,
-    extended_type_info const & base_type,
-    void const * const t,
-    bool top
-){
-    return void_cast_detail::safe_void_caster_registry::upcast(
-        derived_type, base_type, t, top
-    );
-}
-
-BOOST_SERIALIZATION_DECL(void const *)
-void_downcast(
-    const extended_type_info & derived_type,
-    const extended_type_info & base_type,
-    const void * const t,
-    bool top
-){
-    return void_cast_detail::safe_void_caster_registry::downcast(
-        derived_type, base_type, t, top
-    );
+    return NULL;
 }
 
 } // namespace serialization
 } // namespace boost
 
+// EOF