
Hi, Robert Ramey wrote:
Have you considered this any more? I understand the issue but I'm not convinced that your fix is the best one. This would permit code for serializaton of the same type to reside in different DLLS with out the guarentee that all the code is the same.
I don't see much that can be done about that. But assuming that all DLLs were built with the same version of the header files that contain serialization code (or in other words, assuming the One Definition Rule is not violated), the code should be identical.
Also, I'm not conviced that our system of purging global map entries when a DLL containing serialization for a type is unloaded wouldn't create problems. That is I'm not sure that purging all the entries for a given type will be the right thing to do.
I'm thinking that the best would be to detect the case when a duplicate extended_type_info record is added to the corresponding global map and
Considering that DLLs can be unloaded dynamically, it is probably not necessarily the right thing to do. However, this is a hard problem and requires a bit of redesign in Boost.Serialization. The only way to get rid of the problem that I can see is to make sure that all the objects stored in all global registries (i.e. the type info registry, the pointer serializer maps, and the void caster registry) are allocated only once and on the heap of the Boost.Serialization DLL (preferably using some kind of small heap allocator optimization since the objects stored in the map are all of small sizes). So for example, consider the static pointer_iserializer instances in iserializer.hpp, which can potentially be included by multiple DLLs, thus causing multiple pointer_iserializer objects for the same type T to be contained in multiple DLLs. This must be prevented. So instead of directly having static const pointer_iserializer instance; it would be better to have something like static const pointer_iserializer_reference instance; which is only a smart pointer or smart reference to the actual pointer_iserializer object for a type T. This pointer_iserializer object is only allocated _once_ and on the heap of the Boost.Serialization DLL. Now, if multiple DLLs include iserializer.hpp (by including serialization code for the same type T) they will get multiple instances of pointer_iserializer_reference objects. But that's okay now, since only the first time such a reference object is instantiated, the "real" pointer_iserializer object is created. All subsequent DLLs that get loaded and create a pointer_iserializer_reference object for type T will get back the same pointer_iserializer object that was created previously. pointer_iserializer_reference acts as a smart pointer to a unique pointer_iserializer object for type T. So now we don't have any problems when DLLs that contain serialization code for type T get unloaded. They simply decrease the reference count to the pointer_iserializer object. When the last DLL gets unloaded, the reference count drops to 0 and Boost.Serialization can destroy the pointer_iserializer object for type T. I believe, this approach should work with all types of global objects, i.e. void_caster, pointer_iserializer, pointer_oserializer, and extended_type_info. It should also work in all situations I can think of with DLLs on Windows, i.e. with DLLs loaded at startup and unloaded at shutdown and with DLLs that are loaded/unloaded explicitly during run-time. throw
an exception. I see no other way at this point to guarentee that the system will always work.
This would break all our current code base. When you use DLLs and you have serialization code in one DLL that is then used by another DLL, then - with the current use of (effectively global) static member variables in e.g. pointer_iserializer - you _will_ get multiple objects registered in the global registries and maps. There's nothing you can do about that (at least not on Windows; I believe with the Linux loader this problem does not occur). Throwing an exception if this happens, makes using Boost.Serialization with DLLs impossible. Best Regards, Martin TAB Austria Haiderstraße 40 4052 Ansfelden Austria Phone: +43 7229 78040-218 Fax: +43 7229 78040-209 E-mail: martin.ecker@tab.at http://www.tab.at