Boost logo

Boost-Commit :

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


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk