[serialization] The problems with CW...

I took some time to take a closer look at what the current test failures could be about on the cw-8.3 compiler... before I go on vacation. Specifically I looked at the test_exported errors as those seemed to be common to both the 9 and 8 versions of CW. My findings... I managed to get the export tests to *pass* by modifying the test itself (see attached). The problems boils down to the behavior of CW to only instantiate templates when they are used. This not just applies to class templates, but to template methods. In the case of the exported tests it does not instantiate two important things: a) The serialize template method of non-directly referenced derived classes. Specifically for test_exported: polymorphic_derived1::serialize<test_oarchive>, polymorphic_derived1::serialize<test_iarchive>, polymorphic_derived2::serialize<test_oarchive>, and polymorphic_derived2::serialize<test_iarchive>. Forcing those to be instantiated generates all the rest of the self registration code for the derived classes. This still leaves: b) The archive serialization instance for the needed specializations is also not generated as they are not directly reference. Only the ones for the base class, polymorphic_base, are generated as that's the class used in the actual de/serialize calls. I'm not sure anything can be done about fixing this for the release as the only solutions I can come up with would involve changing the serialization interfaces. HTH. -- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com - 102708583/icq =================================================================== RCS file: /cvsroot/boost/boost/libs/serialization/test/test_exported.cpp,v retrieving revision 1.4 diff -u -r1.4 test_exported.cpp --- test_exported.cpp 22 Jul 2004 06:39:17 -0000 1.4 +++ test_exported.cpp 29 Oct 2004 19:36:07 -0000 @@ -40,6 +40,7 @@ class polymorphic_derived1 : public polymorphic_base { friend class boost::serialization::access; +public: template<class Archive> void serialize(Archive &ar, const unsigned int /* file_version */){ ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(polymorphic_base); @@ -49,10 +50,19 @@ }; BOOST_CLASS_EXPORT(polymorphic_derived1) +namespace { + void (polymorphic_derived1::* pd1so_p)(test_oarchive &,const unsigned int) = &polymorphic_derived1::serialize<test_oarchive>; + void (polymorphic_derived1::* pd1si_p)(test_iarchive &,const unsigned int) = &polymorphic_derived1::serialize<test_iarchive>; +} +template<> +const boost::archive::detail::pointer_iserializer<polymorphic_derived1, test_iarchive> boost::archive::detail::pointer_iserializer<polymorphic_derived1, test_iarchive>::instance; +template<> +const boost::archive::detail::pointer_oserializer<polymorphic_derived1, test_oarchive> boost::archive::detail::pointer_oserializer<polymorphic_derived1, test_oarchive>::instance; class polymorphic_derived2 : public polymorphic_base { friend class boost::serialization::access; +public: template<class Archive> void serialize(Archive &ar, const unsigned int /* file_version */){ ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(polymorphic_base); @@ -62,6 +72,14 @@ }; BOOST_CLASS_EXPORT(polymorphic_derived2) +namespace { + void (polymorphic_derived2::* pd2so_p)(test_oarchive &,const unsigned int) = &polymorphic_derived2::serialize<test_oarchive>; + void (polymorphic_derived2::* pd2si_p)(test_iarchive &,const unsigned int) = &polymorphic_derived2::serialize<test_iarchive>; +} +template<> +const boost::archive::detail::pointer_iserializer<polymorphic_derived2, test_iarchive> boost::archive::detail::pointer_iserializer<polymorphic_derived2, test_iarchive>::instance; +template<> +const boost::archive::detail::pointer_oserializer<polymorphic_derived2, test_oarchive> boost::archive::detail::pointer_oserializer<polymorphic_derived2, test_oarchive>::instance; // save exported polymorphic class void save_exported(const char *testfile)

Thanks for looking into this. This more or less ratifies my suspicions as to the origin of ths problem. "Rene Rivera" <grafik.list@redshift-software.com> wrote in message news:4182A275.1010105@redshift-software.com...
I took some time to take a closer look at what the current test failures could be about on the cw-8.3 compiler... before I go on vacation. Specifically I looked at the test_exported errors as those seemed to be common to both the 9 and 8 versions of CW. My findings...
I managed to get the export tests to *pass* by modifying the test itself (see attached). The problems boils down to the behavior of CW to only instantiate templates when they are used. This not just applies to class templates, but to template methods.
Agreed
a) The serialize template method of non-directly referenced derived classes. Specifically for test_exported: polymorphic_derived1::serialize<test_oarchive>, polymorphic_derived1::serialize<test_iarchive>, polymorphic_derived2::serialize<test_oarchive>, and polymorphic_derived2::serialize<test_iarchive>.
Forcing those to be instantiated generates all the rest of the self registration code for the derived classes. This still leaves:
b) The archive serialization instance for the needed specializations is also not generated as they are not directly reference. Only the ones for the base class, polymorphic_base, are generated as that's the class used in the actual de/serialize calls.
I'm not sure anything can be done about fixing this for the release
Agreed.
as the only solutions I can come up with would involve changing the serialization interfaces.
The original verision ofthe library didn't have ths problem. It required "pre-registration" of types to be serialized via polymorphic pointers. Strenous objection was raised in some quarters due to the believe that this placed an unreasonable burden on library users and would require that "upperlevels" know about all the components. It was also pointed out that this would make the concept of certain types of "plug-ins' untenable. So it would be easy to say - If you're using CW, just make sure you "register" all you're derived pointers. Unfortunately, even that doesn't work for CW because instantiating the class doesn't instantiate all the member functions. I don't think that CW is incorrect in this. Its just that this behavior is not desired in some cases. Another case where this is a problem is the implementation of a DLL. We implement functions but they are not explicitly called. we use "_export" keywords to indicate that these functions should be instantiated and not optimised away even though the functions are not explicitly called by name. This method resolved the issue for all other platforms. It doesn't conform to any standard that I know of. I don't there is a standard conforming way of specifying this behavior. Unfortunately, CW doesn't seem to respond in this way to the "export" keyword - even though it accepts it. It leaves me wondering how one makes a DLL in CW without losing all the functions in the compiled object. I searched high and low for a compiler switch and/or pragma that would fix this - but was unsuccessful. This means that for now on CW, derived pointers cannot be serialized through their base class. Other aspects of the serialization library still work as advertised. I would guess that we an conjure up some registrtation macros that force instantiation on CW compilers. These would expand to no acton for other compilers. Maybe that would be the best we can do. Robert Ramey

"Robert Ramey" <ramey@rrsd.com> writes:
"Rene Rivera" <grafik.list@redshift-software.com> wrote in message news:4182A275.1010105@redshift-software.com...
I took some time to take a closer look at what the current test failures could be about on the cw-8.3 compiler... before I go on vacation. Specifically I looked at the test_exported errors as those seemed to be common to both the 9 and 8 versions of CW. My findings...
I managed to get the export tests to *pass* by modifying the test itself (see attached). The problems boils down to the behavior of CW to only instantiate templates when they are used. This not just applies to class templates, but to template methods.
Agreed
This should be considered standard portable behavior. If the library is relying on different behavior, a redesign is probably in order (after the release, of course). -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:uacu3nkhm.fsf@boost-consulting.com...
"Robert Ramey" <ramey@rrsd.com> writes:
"Rene Rivera" <grafik.list@redshift-software.com> wrote in message news:4182A275.1010105@redshift-software.com...
I took some time to take a closer look at what the current test failures could be about on the cw-8.3 compiler... before I go on vacation. Specifically I looked at the test_exported errors as those seemed to be common to both the 9 and 8 versions of CW. My findings...
I managed to get the export tests to *pass* by modifying the test itself (see attached). The problems boils down to the behavior of CW to only instantiate templates when they are used. This not just applies to class templates, but to template methods.
Agreed
This should be considered standard portable behavior. If the library is relying on different behavior, a redesign is probably in order (after the release, of course).
Actually, I'm coming to believe that the "export" functionality (demanded by certain users) cannot be implemented in a way that is guarenteed to work for strickly confoming compilers. That is why the code includes a little extra help which is compiler dependent. So if one wants a package which is guarenteed to work for al standard conforming compilers - either one will have to give up on the "export" functionality or add something to the standard to mark code for guarenteed instantiation.
-- Dave Abrahams Boost Consulting http://www.boost-consulting.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

At 05:13 PM 10/29/2004, Robert Ramey wrote:
... I don't think that CW is incorrect in this. Its just that this behavior is not desired in some cases. Another case where this is a problem is the implementation of a DLL. We implement functions but they are not explicitly called. we use "_export" keywords to indicate that these functions should be instantiated and not optimised away even though the functions are not explicitly called by name. This method resolved the issue for all other platforms. It doesn't conform to any standard that I know of. I don't there is a standard conforming way of specifying this behavior. Unfortunately, CW doesn't seem to respond in this way to the "export" keyword - even though it accepts it. It leaves me wondering how one makes a DLL in CW without losing all the functions in the compiled object. I searched high and low for a compiler switch and/or pragma that would fix this - but was unsuccessful.
That sounds like a question you could ask on codewarrior.windows. That newsgroup is closely monitored by several Metrowerks employees, and they are usually pretty good about responding to queries. --Beman
participants (4)
-
Beman Dawes
-
David Abrahams
-
Rene Rivera
-
Robert Ramey