Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r55675 - trunk/boost/serialization
From: ramey_at_[hidden]
Date: 2009-08-20 01:32:15


Author: ramey
Date: 2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
New Revision: 55675
URL: http://svn.boost.org/trac/boost/changeset/55675

Log:
Fix error in export functionality:
a) set key when etf record is constructed.
b) make corrections in no_rtti type system
c) make no_rtti type system more robust and self-diagnosing
Text files modified:
   trunk/boost/serialization/export.hpp | 95 +++++++++++++++++++++------------------
   trunk/boost/serialization/extended_type_info.hpp | 37 +++++++++++---
   trunk/boost/serialization/extended_type_info_no_rtti.hpp | 48 +++++++++++++++++--
   trunk/boost/serialization/extended_type_info_typeid.hpp | 23 ++++++---
   trunk/boost/serialization/version.hpp | 25 ++++++----
   5 files changed, 152 insertions(+), 76 deletions(-)

Modified: trunk/boost/serialization/export.hpp
==============================================================================
--- trunk/boost/serialization/export.hpp (original)
+++ trunk/boost/serialization/export.hpp 2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
@@ -29,14 +29,11 @@
 #include <boost/preprocessor/stringize.hpp>
 #include <boost/type_traits/is_polymorphic.hpp>
 
-#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
- #include <boost/serialization/extended_type_info_typeid.hpp>
-#endif
 #include <boost/serialization/static_warning.hpp>
-#include <boost/serialization/type_info_implementation.hpp>
 #include <boost/serialization/assume_abstract.hpp>
 #include <boost/serialization/force_include.hpp>
 #include <boost/serialization/singleton.hpp>
+#include <boost/serialization/non_convertible.hpp>
 
 #include <boost/archive/detail/register_archive.hpp>
 #include <boost/mpl/assert.hpp>
@@ -118,60 +115,72 @@
     );
 }
 
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
 namespace {
 
 template<class T>
 struct guid_initializer
 {
- const guid_initializer & export_guid(char const* /* key */, mpl::false_){
+ void export_guid(boost::mpl::false_){
         // generates the statically-initialized objects whose constructors
         // register the information allowing serialization of T objects
         // through pointers to their base classes.
- instantiate_ptr_serialization((T*)0, 0, adl_tag());
- return *this;
+ boost::archive::detail::instantiate_ptr_serialization(
+ (T*)0,
+ 0,
+ boost::archive::detail::adl_tag()
+ );
     }
- const guid_initializer & export_guid(char const* /*key*/, mpl::true_){
- return *this;
- }
- const guid_initializer & export_guid(char const* key){
+ void export_guid(boost::mpl::true_){}
+ guid_initializer(){
         BOOST_STATIC_WARNING(boost::is_polymorphic<T>::value);
- assert(NULL != key);
- boost::serialization::singleton<
- BOOST_DEDUCED_TYPENAME
- boost::serialization::type_info_implementation<T>::type
- >::get_mutable_instance().key_register(key);
         // note: exporting an abstract base class will have no effect
         // and cannot be used to instantitiate serialization code
         // (one might be using this in a DLL to instantiate code)
         //BOOST_STATIC_WARNING(! boost::serialization::is_abstract<T>::value);
- return export_guid(key, boost::serialization::is_abstract<T>());
+ export_guid(boost::serialization::is_abstract<T>());
     }
 };
 
-template<typename T>
-struct init_guid;
+template<class T>
+struct init_guid {
+ static guid_initializer< T > const & g;
+};
 
 } // anonymous
-} // namespace detail
-} // namespace archive
-} // namespace boost
 
-#define BOOST_CLASS_EXPORT_GUID(T, K) \
- namespace boost { \
- namespace archive { \
- namespace detail { \
+#define BOOST_CLASS_EXPORT_IMPLEMENT(T) \
     namespace { \
- template<> \
- struct init_guid< T > { \
- static ::boost::archive::detail::guid_initializer< T > const \
- & guid_initializer; \
- }; \
- ::boost::archive::detail::guid_initializer< T > const & \
- ::boost::archive::detail::init_guid< T >::guid_initializer = \
+ template <> guid_initializer< T > const & init_guid< T >::g = \
            ::boost::serialization::singleton< \
- ::boost::archive::detail::guid_initializer< T > \
- >::get_mutable_instance().export_guid(K); \
- }}}} \
+ guid_initializer< T > \
+ >::get_mutable_instance(); \
+ } \
+/**/
+
+#define BOOST_CLASS_EXPORT_KEY2(T, K) \
+namespace boost { \
+namespace serialization { \
+template<> \
+struct guid_defined<T> : boost::mpl::true_ {}; \
+template<> \
+inline const char * guid<T>(){ \
+ return K; \
+} \
+} /* serialization */ \
+} /* boost */ \
+/**/
+
+#define BOOST_CLASS_EXPORT_KEY(T) \
+ BOOST_CLASS_EXPORT_KEY2(T, BOOST_PP_STRINGIZE(T)) \
+/**/
+
+#define BOOST_CLASS_EXPORT_GUID(T, K) \
+BOOST_CLASS_EXPORT_KEY2(T, K) \
+BOOST_CLASS_EXPORT_IMPLEMENT(T) \
 /**/
 
 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
@@ -181,13 +190,13 @@
 // compiler we ask users to specifically register base/derived class
 // relationships for exported classes. On all other compilers, use of
 // this macro is entirely optional.
-# define BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(Base,Derived) \
-namespace { \
- static int BOOST_PP_CAT(boost_serialization_mwerks_init_, __LINE__) = \
- (::boost::archive::detail::instantiate_ptr_serialization((Derived*)0,0), 3); \
- static int BOOST_PP_CAT(boost_serialization_mwerks_init2_, __LINE__) = ( \
- ::boost::serialization::void_cast_register((Derived*)0,(Base*)0) \
- , 3); \
+# define BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(Base,Derived) \
+namespace { \
+ static int BOOST_PP_CAT(boost_serialization_mwerks_init_, __LINE__) = \
+ (::boost::archive::detail::instantiate_ptr_serialization((Derived*)0,0), 3); \
+ static int BOOST_PP_CAT(boost_serialization_mwerks_init2_, __LINE__) = ( \
+ ::boost::serialization::void_cast_register((Derived*)0,(Base*)0) \
+ , 3); \
 }
 
 #else

Modified: trunk/boost/serialization/extended_type_info.hpp
==============================================================================
--- trunk/boost/serialization/extended_type_info.hpp (original)
+++ trunk/boost/serialization/extended_type_info.hpp 2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
@@ -26,6 +26,7 @@
 #include <boost/serialization/config.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/weak_ptr.hpp>
+#include <boost/mpl/bool.hpp>
 
 #include <boost/config/abi_prefix.hpp> // must be the last header
 #ifdef BOOST_MSVC
@@ -35,13 +36,24 @@
 
 #define BOOST_SERIALIZATION_MAX_KEY_SIZE 128
 
+
 namespace boost {
 namespace serialization {
+
+namespace void_cast_detail{
+ class void_caster;
+}
+
 class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) extended_type_info :
     private boost::noncopyable
 {
-private:
+private:
+ friend class boost::serialization::void_cast_detail::void_caster;
     boost::shared_ptr<const extended_type_info> m_this;
+ boost::weak_ptr<const extended_type_info>
+ get_weak_ptr() const {
+ return m_this;
+ }
 
     // used to uniquely identify the type of class derived from this one
     // so that different derivations of this class can be simultaneously
@@ -49,13 +61,18 @@
     const unsigned int m_type_info_key;
     virtual bool is_less_than(const extended_type_info & /*rhs*/) const = 0;
     virtual bool is_equal(const extended_type_info & /*rhs*/) const = 0;
- void key_unregister();
-protected:
     const char * m_key;
+
+protected:
+ void key_unregister() const;
+ void key_register() const;
     // this class can't be used as is. It's just the
     // common functionality for all type_info replacement
     // systems. Hence, make these protected
- extended_type_info(const unsigned int type_info_key = 0);
+ extended_type_info(
+ const unsigned int type_info_key,
+ const char * key
+ );
     // account for bogus gcc warning
     #if defined(__GNUC__)
     virtual
@@ -65,16 +82,11 @@
     const char * get_key() const {
         return m_key;
     }
- void key_register(const char *key);
     bool operator<(const extended_type_info &rhs) const;
     bool operator==(const extended_type_info &rhs) const;
     bool operator!=(const extended_type_info &rhs) const {
         return !(operator==(rhs));
     }
- boost::weak_ptr<const extended_type_info>
- get_weak_ptr() const {
- return m_this;
- }
     static const extended_type_info * find(const char *key);
     // for plugins
     virtual void * construct(unsigned int /*count*/ = 0, ...) const {
@@ -86,6 +98,13 @@
     }
 };
 
+template<class T>
+struct guid_defined : boost::mpl::false_ {};
+template<class T>
+inline const char * guid(){
+ return NULL;
+}
+
 } // namespace serialization
 } // namespace boost
 

Modified: trunk/boost/serialization/extended_type_info_no_rtti.hpp
==============================================================================
--- trunk/boost/serialization/extended_type_info_no_rtti.hpp (original)
+++ trunk/boost/serialization/extended_type_info_no_rtti.hpp 2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
@@ -25,6 +25,9 @@
 #include <boost/serialization/singleton.hpp>
 #include <boost/serialization/extended_type_info.hpp>
 #include <boost/serialization/factory.hpp>
+#include <boost/serialization/throw_exception.hpp>
+
+#include <boost/mpl/if.hpp>
 
 #include <boost/config/abi_prefix.hpp> // must be the last header
 #ifdef BOOST_MSVC
@@ -38,7 +41,7 @@
 // define a special type_info that doesn't depend on rtti which is not
 // available in all situations.
 
-namespace detail {
+namespace no_rtti_system {
 
 // common base class to share type_info_key. This is used to
 // identify the method used to keep track of the extended type
@@ -46,7 +49,7 @@
     public extended_type_info
 {
 protected:
- extended_type_info_no_rtti_0();
+ extended_type_info_no_rtti_0(const char * key);
     ~extended_type_info_no_rtti_0();
 public:
     virtual bool
@@ -55,17 +58,47 @@
     is_equal(const boost::serialization::extended_type_info &rhs) const ;
 };
 
-} // detail
+} // no_rtti_system
 
 template<class T>
 class extended_type_info_no_rtti :
- public detail::extended_type_info_no_rtti_0,
+ public no_rtti_system::extended_type_info_no_rtti_0,
     public singleton<extended_type_info_no_rtti<T> >
 {
+ template<bool tf>
+ struct action {
+ struct defined {
+ static const char * invoke(){
+ return guid<T>();
+ }
+ };
+ struct undefined {
+ // if your program traps here - you failed to
+ // export a guid for this type. the no_rtti
+ // system requires export for types serialized
+ // as pointers.
+ BOOST_STATIC_ASSERT(0 == sizeof(T));
+ static const char * invoke();
+ };
+ static const char * invoke(){
+ typedef
+ BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
+ tf,
+ defined,
+ undefined
+ >::type type;
+ return type::invoke();
+ }
+ };
 public:
     extended_type_info_no_rtti() :
- detail::extended_type_info_no_rtti_0()
- {}
+ no_rtti_system::extended_type_info_no_rtti_0(get_key())
+ {
+ key_register();
+ }
+ ~extended_type_info_no_rtti(){
+ key_unregister();
+ }
     const extended_type_info *
     get_derived_extended_type_info(const T & t) const {
         // find the type that corresponds to the most derived type.
@@ -77,6 +110,9 @@
         assert(NULL != derived_key);
         return boost::serialization::extended_type_info::find(derived_key);
     }
+ const char * get_key() const{
+ return action<guid_defined<T>::value >::invoke();
+ }
     void * construct(unsigned int count, ...) const{
         // count up the arguments
         std::va_list ap;

Modified: trunk/boost/serialization/extended_type_info_typeid.hpp
==============================================================================
--- trunk/boost/serialization/extended_type_info_typeid.hpp (original)
+++ trunk/boost/serialization/extended_type_info_typeid.hpp 2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
@@ -32,6 +32,8 @@
 #include <boost/serialization/extended_type_info.hpp>
 #include <boost/serialization/factory.hpp>
 
+#include <boost/mpl/if.hpp>
+
 #include <boost/config/abi_prefix.hpp> // must be the last header
 #ifdef BOOST_MSVC
 # pragma warning(push)
@@ -40,14 +42,14 @@
 
 namespace boost {
 namespace serialization {
-namespace detail {
+namespace typeid_system {
 
 class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) extended_type_info_typeid_0 :
     public extended_type_info
 {
 protected:
     const std::type_info * m_ti;
- extended_type_info_typeid_0();
+ extended_type_info_typeid_0(const char * key);
     ~extended_type_info_typeid_0();
     void type_register(const std::type_info & ti);
     void type_unregister();
@@ -63,20 +65,22 @@
     }
 };
 
-} // namespace detail
+} // typeid_system
 
 template<class T>
 class extended_type_info_typeid :
- public detail::extended_type_info_typeid_0,
+ public typeid_system::extended_type_info_typeid_0,
     public singleton<extended_type_info_typeid<T> >
 {
 public:
     extended_type_info_typeid() :
- detail::extended_type_info_typeid_0()
+ typeid_system::extended_type_info_typeid_0(get_key())
     {
         type_register(typeid(T));
+ key_register();
     }
     ~extended_type_info_typeid(){
+ key_unregister();
         type_unregister();
     }
     // get the eti record for the true type of this record
@@ -87,11 +91,14 @@
         // only does something if the class has at least one virtual function.
         BOOST_STATIC_WARNING(boost::is_polymorphic<T>::value);
         return
- detail::extended_type_info_typeid_0::get_extended_type_info(
+ typeid_system::extended_type_info_typeid_0::get_extended_type_info(
                 typeid(t)
             );
     }
- void * construct(unsigned int count, ...) const{
+ const char * get_key() const {
+ return boost::serialization::guid<T>();
+ }
+ virtual void * construct(unsigned int count, ...) const{
         // count up the arguments
         std::va_list ap;
         va_start(ap, count);
@@ -112,7 +119,7 @@
             return NULL;
         }
     }
- void destroy(void const * const /* p */) const {
+ virtual void destroy(void const * const /* p */) const {
         // the only current usage of extended type info is in the
         // serialization library. The statement below requires
         // that destructor of type T be public and this creates

Modified: trunk/boost/serialization/version.hpp
==============================================================================
--- trunk/boost/serialization/version.hpp (original)
+++ trunk/boost/serialization/version.hpp 2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
@@ -55,6 +55,18 @@
 } // namespace serialization
 } // namespace boost
 
+/* note: at first it seemed that this would be a good place to trap
+ * as an error an attempt to set a version # for a class which doesn't
+ * save its class information (including version #) in the archive.
+ * However, this imposes a requirement that the version be set after
+ * the implemention level which would be pretty confusing. If this
+ * is to be done, do this check in the input or output operators when
+ * ALL the serialization traits are available. Included the implementation
+ * here with this comment as a reminder not to do this!
+ */
+//#include <boost/serialization/level.hpp>
+//#include <boost/mpl/equal_to.hpp>
+
 // specify the current version number for the class
 #define BOOST_CLASS_VERSION(T, N) \
 namespace boost { \
@@ -65,18 +77,11 @@
     typedef mpl::int_<N> type; \
     typedef mpl::integral_c_tag tag; \
     BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value); \
- /* require that class info saved when versioning is used */ \
     /* \
     BOOST_STATIC_ASSERT(( \
- mpl::or_< \
- mpl::equal_to< \
- mpl::int_<0>, \
- mpl::int_<N> \
- >, \
- mpl::equal_to< \
- implementation_level<T>, \
- mpl::int_<object_class_info> \
- > \
+ mpl::equal_to< \
+ :implementation_level<T >, \
+ mpl::int_<object_class_info> \
>::value \
     )); \
     */ \


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