Boost logo

Boost :

From: martin.ecker_at_[hidden]
Date: 2005-09-02 04:49:10


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.

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.

> 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
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_at_[hidden]
http://www.tab.at


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk