[serialization] BOOST_CLASS_EXPORT worries

I recall that I did suggested one approach. BOOST_CLASS_EXPORT can register the class with all previously included archives and, unconditionally, with polymorphic archive. During saving, you can check if the saved class is registered with specific archive type. If not, you wrap archive in polymorphic archive and save. That would be slower, but in most situation extra virtual function call won't be a practical problem.
In the rare case where it will be a problem, user can: 1. Include necessary archive headers 2. Invoke BOOST_CLASS_EXPORT *again* in his module, after including another archive header. If BOOST_CLASS_EXPORT tolerates multiple invocations, this will instantiate the code for the needed archive type, and make saving to that archive type go without polymorphic arhive.
export.hpp is already quite complicated. This would seem to add a huge amount of effort at compiler and at rntime.
Why? From my naive point of view, that would be a simple comparison when saving. As for double registering -- I suppose that if registration data is kept in some std::map, then there are problems at all.
It would also add dead code to almos t every executable using the library.
IMO, this is clearly better than instantiate all of serialization library once for each archive type.
It would seem a huge price to pay just to permit one to say.
#include <boost/serialization/export.hpp #include <boost/archive/text_iarchive.hpp>
rather than
#include <boost/archive/text_iarchive.hpp> #include <boost/serialization/export.hpp
No, there's a different concern -- the current approach does not scale. Say I have my_class.hpp and my_class.cpp. Somewhere in those files I have BOOST_CLASS_EXPORT, which instantiates serialization code for a number of archive types. Now I write a new archive type, in my_cool_archive.cpp. Suddenly, serialization of MyClass does not work. Now I need to add another include to my_class.cpp and too all other files that have BOOST_CLASS_EXPORT in it. That's no good. Now consider that a class is defined in a plugin. IIRC, that was one of the motivating examples for BOOST_CLASS_EXPORT. The situation becomes worse -- if a plugin is built with N archive types, and is packaged in binary form, but application defines it's own archive type, then serializing a class from plugin using that new archive type is not possible. Now assume that we don't have plugins and applications written by the same developer, but just a shared library. Say, I want to write a library for manipulating EBNF grammar and want to add serialization. Client applications are not written by me at all. Now if that application defines a new archive type, nothing will work. Not to mention that I'm not happy with bloating my library with code for 5 archive types (binary, text, xml + wide variants of the latter two). - Volodya

Vladimir Prus wrote:
I recall that I did suggested one approach. BOOST_CLASS_EXPORT can register the class with all previously included archives and, unconditionally, with polymorphic archive. During saving, you can check if the saved class is registered with specific archive type. If not, you wrap archive in polymorphic archive and save. That would be slower, but in most situation extra virtual function call won't be a practical problem.
In the rare case where it will be a problem, user can: 1. Include necessary archive headers 2. Invoke BOOST_CLASS_EXPORT *again* in his module, after including another archive header. If BOOST_CLASS_EXPORT tolerates multiple invocations, this will instantiate the code for the needed archive type, and make saving to that archive type go without polymorphic arhive.
export.hpp is already quite complicated. This would seem to add a huge amount of effort at compiler and at rntime.
Why? From my naive point of view, that would be a simple comparison when saving. As for double registering -- I suppose that if registration data is kept in some std::map, then there are problems at all.
I have to confess I don't really understand the above. Maybe it just sounds complicated.
It would also add dead code to almos t every executable using the library.
IMO, this is clearly better than instantiate all of serialization library once for each archive type.
Note that serialization is instantiated only for archive whose headers are included.
It would seem a huge price to pay just to permit one to say.
#include <boost/serialization/export.hpp #include <boost/archive/text_iarchive.hpp>
rather than
#include <boost/archive/text_iarchive.hpp> #include <boost/serialization/export.hpp
No, there's a different concern -- the current approach does not scale. Say I have my_class.hpp and my_class.cpp. Somewhere in those files I have BOOST_CLASS_EXPORT, which instantiates serialization code for a number of archive types. Now I write a new archive type, in my_cool_archive.cpp. Suddenly, serialization of MyClass does not work. Now I need to add another include to my_class.cpp and too all other files that have BOOST_CLASS_EXPORT in it. That's no good.
Now consider that a class is defined in a plugin. IIRC, that was one of the motivating examples for BOOST_CLASS_EXPORT. The situation becomes worse -- if a plugin is built with N archive types, and is packaged in binary form, but application defines it's own archive type, then serializing a class from plugin using that new archive type is not possible.
Now assume that we don't have plugins and applications written by the same developer, but just a shared library. Say, I want to write a library for manipulating EBNF grammar and want to add serialization. Client applications are not written by me at all. Now if that application defines a new archive type, nothing will work. Not to mention that I'm not happy with bloating my library with code for 5 archive types (binary, text, xml + wide variants of the latter two).
For this we have the polymorphic_ archives. Compile once with the polymorphic archive headers. Now your code is compatible with all archives past and future. At least that is my intent. Is there some reason this doesn't work as intended? Note that your serialization code contains code for only one archive - the polymorphic archive. There is no instantiation of code for the other archive classes. The only cost is a teensy bit of execution time as as archive calls are redirected through a vtable. Robert Ramey

Robert Ramey wrote:
Now assume that we don't have plugins and applications written by the same developer, but just a shared library. Say, I want to write a library for manipulating EBNF grammar and want to add serialization. Client applications are not written by me at all. Now if that application defines a new archive type, nothing will work. Not to mention that I'm not happy with bloating my library with code for 5 archive types (binary, text, xml + wide variants of the latter two).
For this we have the polymorphic_ archives. Compile once with the polymorphic archive headers. Now your code is compatible with all archives past and future. At least that is my intent. Is there some reason this doesn't work as intended? Note that your serialization code contains code for only one archive - the polymorphic archive. There is no instantiation of code for the other archive classes. The only cost is a teensy bit of execution time as as archive calls are redirected through a vtable.
Exactly. Now consider that I have a .cpp file that has BOOST_CLASS_EXPORT. I don't know what kinds of archives will be used to serialize classes defined in .cpp. So, I need to *always* #include polymorphic_archive headers. If I don't include polymorphic archive, I'd need to include all standard archive types (again, I have no idea which archive type will be actually used), and that will instantiate a lot of code. Why not make include polymorphic_archive automatic? And make other archive types resort to polymorphic_archive when no serialization for that archive type was BOOST_CLASS_EXPORTED. As you say, the only cost is a "teensy bit of execution time", in most cases users won't even notice, but the code size will be reduced. - Volodya
participants (2)
-
Robert Ramey
-
Vladimir Prus