Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r51676 - in trunk/libs/serialization: src test
From: ramey_at_[hidden]
Date: 2009-03-09 19:41:43


Author: ramey
Date: 2009-03-09 19:41:43 EDT (Mon, 09 Mar 2009)
New Revision: 51676
URL: http://svn.boost.org/trac/boost/changeset/51676

Log:
checked in new type trait - is_virtual_base_of.hpp
changes to speed up void cast
Text files modified:
   trunk/libs/serialization/src/void_cast.cpp | 283 ++++++++++++++++++++-------------------
   trunk/libs/serialization/test/test_diamond.cpp | 2
   2 files changed, 149 insertions(+), 136 deletions(-)

Modified: trunk/libs/serialization/src/void_cast.cpp
==============================================================================
--- trunk/libs/serialization/src/void_cast.cpp (original)
+++ trunk/libs/serialization/src/void_cast.cpp 2009-03-09 19:41:43 EDT (Mon, 09 Mar 2009)
@@ -17,7 +17,7 @@
 #include <cstddef> // NULL
 
 // STL
-#include <vector>
+#include <set>
 #include <functional>
 #include <algorithm>
 #include <cassert>
@@ -34,92 +34,105 @@
 namespace serialization {
 namespace void_cast_detail {
 
-typedef std::vector<const void_caster *> set_type;
-typedef boost::serialization::singleton<set_type> void_caster_registry;
-
-inline bool
-void_caster::operator==(void_caster const & rhs) const{
- if(m_derived != rhs.m_derived)
- return false;
- if(m_base != rhs.m_base)
- return false;
- return true;
-}
-
-// 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)
-{}
-
-BOOST_SERIALIZATION_DECL(void)
-void_caster::static_register() const {
- void_caster_registry::get_mutable_instance().push_back(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;
+struct void_caster_compare {
+ bool operator()(const void_caster * lhs, const void_caster * rhs) const {
+ return *lhs < *rhs;
     }
- */
-}
+};
 
-BOOST_SERIALIZATION_DECL(void)
-void_caster::static_unregister() const {
- if(! void_caster_registry::is_destroyed()){
- void_cast_detail::set_type & st
- = void_caster_registry::get_mutable_instance();
- void_cast_detail::set_type::iterator it;
- it = std::find(st.begin(), st.end(), 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;
- }
- */
- }
-}
+typedef std::set<const void_caster *, void_caster_compare> set_type;
+typedef boost::serialization::singleton<set_type> void_caster_registry;
 
-#if 0
 // implementation of shortcut void caster
-class void_caster_derived : public void_caster
+class void_caster_shortcut : public void_caster
 {
- std::ptrdiff_t difference;
+ bool m_includes_virtual_base;
+
+ void const *
+ vbc_upcast(
+ void const * const t
+ ) const;
+ void const *
+ vbc_downcast(
+ void const * const t
+ ) const;
     virtual void const *
     upcast(void const * const t) const{
- return static_cast<const char *> ( t ) + difference;
+ if(m_includes_virtual_base)
+ return vbc_upcast(t);
+ return static_cast<const char *> ( t ) - m_difference;
     }
     virtual void const *
     downcast(void const * const t) const{
- return static_cast<const char *> ( t ) - difference;
+ if(m_includes_virtual_base)
+ return vbc_downcast(t);
+ return static_cast<const char *> ( t ) + m_difference;
+ }
+ virtual bool is_shortcut() const {
+ return true;
     }
 public:
- void_caster_derived(
- extended_type_info const & derived,
- extended_type_info const & base,
- std::ptrdiff_t difference
+ void_caster_shortcut(
+ extended_type_info const * derived,
+ extended_type_info const * base,
+ std::ptrdiff_t difference,
+ bool m_includes_virtual_base
     ) :
- void_caster(derived, base),
- difference( difference )
+ void_caster(derived, base, difference)
     {
- this->static_register();
+ recursive_register(m_includes_virtual_base);
     }
- ~void_caster_derived(){
- this->static_unregister();
+ ~void_caster_shortcut(){
+ recursive_unregister();
     }
 };
-#endif
+
+void const *
+void_caster_shortcut::vbc_downcast(
+ void const * const t
+) const {
+ // try to find a chain that gives us what we want
+ const void_cast_detail::set_type & s
+ = void_cast_detail::void_caster_registry::get_const_instance();
+ void_cast_detail::set_type::const_iterator it;
+ for(it = s.begin(); it != s.end(); ++it){
+ // if the current candidate doesn't cast to the desired target type
+ if ((*it)->m_derived == m_derived){
+ // if the current candidate casts from the desired source type
+ if ((*it)->m_base != m_base){
+ const void * t_new;
+ t_new = void_downcast(*(*it)->m_base, *m_base, t);
+ if(NULL != t_new)
+ return (*it)->downcast(t_new);
+ }
+ }
+ }
+ return NULL;
+}
+
+void const *
+void_caster_shortcut::vbc_upcast(
+ void const * const t
+) const {
+ // try to find a chain that gives us what we want
+ const void_cast_detail::set_type & s
+ = void_cast_detail::void_caster_registry::get_const_instance();
+ void_cast_detail::set_type::const_iterator 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 == m_base){
+ // if the current candidate casts from the desired source type
+ if ((*it)->m_derived != m_derived){
+ const void * t_new;
+ t_new = void_upcast(*m_derived, *(*it)->m_derived, t);
+ if(NULL != t_new)
+ return (*it)->upcast(t_new);
+ }
+ }
+ }
+ return NULL;
+}
+
 
 // just used as a search key
 class void_caster_argument : public void_caster
@@ -136,24 +149,72 @@
     }
 public:
     void_caster_argument(
- extended_type_info const & derived,
- extended_type_info const & base
+ extended_type_info const * derived,
+ extended_type_info const * base
     ) :
         void_caster(derived, base)
     {}
     ~void_caster_argument(){};
 };
 
-struct match {
- void_cast_detail::void_caster_argument const * const m_ca;
+// implementation of void caster base class
+BOOST_SERIALIZATION_DECL(void)
+void_caster::recursive_register(bool includes_virtual_base) const {
+ void_cast_detail::set_type & s
+ = void_cast_detail::void_caster_registry::get_mutable_instance();
+
+ s.insert(this);
+
+ // generate all implied void_casts.
+
+ void_cast_detail::set_type::const_iterator it;
+ for(it = s.begin(); it != s.end(); ++it){
+ if(m_derived == (*it)->m_base)
+ new void_caster_shortcut(
+ (*it)->m_derived,
+ m_base,
+ m_difference + (*it)->m_difference,
+ includes_virtual_base
+ );
+ if((*it)->m_derived == m_base)
+ new void_caster_shortcut(
+ m_derived,
+ (*it)->m_base,
+ m_difference + (*it)->m_difference,
+ includes_virtual_base
+ );
+ }
+}
+
+BOOST_SERIALIZATION_DECL(void)
+void_caster::recursive_unregister() const {
+ if(void_caster_registry::is_destroyed())
+ return;
+
+ void_cast_detail::set_type & s
+ = void_caster_registry::get_mutable_instance();
+
+ // delete all implied void_casts.
+ void_cast_detail::set_type::iterator it;
+ for(it = s.begin(); it != s.end(); ++it){
+ if((*it)->is_shortcut()){
+ if(m_derived == (*it)->m_base
+ || (*it)->m_derived == m_base){
+ delete *it;
+ it = s.begin();
+ }
+ }
+ }
+
+ const void_cast_detail::void_caster_argument ca(m_derived, m_base);
+ it = s.find(& ca);
+ if(s.end() == it)
+ return;
+
+ s.erase(it);
+}
+
 
- match(void_cast_detail::void_caster_argument const * const ca) :
- m_ca(ca)
- {}
- bool operator()(const void_cast_detail::void_caster * vc){
- return * vc == * m_ca;
- };
-};
 
 } // namespace void_cast_detail
 
@@ -174,36 +235,13 @@
     // check to see if base/derived pair is found in the registry
     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);
+ void_cast_detail::void_caster_argument ca(& derived, & base);
 
- it = std::find_if(
- s.begin(),
- s.end(),
- void_cast_detail::match(& ca)
- );
-
- // if so
+ void_cast_detail::set_type::const_iterator it;
+ it = s.find(& ca);
     if (s.end() != it)
- // we're done
         return (*it)->upcast(t);
 
- // try to find a chain that gives us what we want
- for(it = s.begin(); it != s.end(); ++it){
- // if the current candidate doesn't cast to the desired target type
- if((*it)->m_base == base){
- // if the current candidate casts from the desired source type
- if ((*it)->m_derived == derived){
- // we have a base/derived match - we're done
- // cast to the intermediate type
- 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 NULL;
 }
 
@@ -220,40 +258,15 @@
     // check to see if base/derived pair is found in the registry
     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);
+ void_cast_detail::void_caster_argument ca(& derived, & base);
 
- it = std::find_if(
- s.begin(),
- s.end(),
- void_cast_detail::match(& ca)
- );
-
- // if so
+ void_cast_detail::set_type::const_iterator it;
+ it = s.find(&ca);
     if (s.end() != it)
- // we're done
         return(*it)->downcast(t);
 
- // try to find a chain that gives us what we want
- 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
- 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 NULL;
 }
 
 } // namespace serialization
 } // namespace boost
-
-// EOF

Modified: trunk/libs/serialization/test/test_diamond.cpp
==============================================================================
--- trunk/libs/serialization/test/test_diamond.cpp (original)
+++ trunk/libs/serialization/test/test_diamond.cpp 2009-03-09 19:41:43 EDT (Mon, 09 Mar 2009)
@@ -63,7 +63,7 @@
     {
         return i == another.i && m == another.m;
     }
- // make virtual to evade gcc quirk
+ // make polymorphic by marking at least one function virtual
     virtual ~base() {};
 private:
     int i;


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