
Vladimir Prus wrote:
I havn't considered it in detail but its easy to consider using a semaphore (even though I'm sure there are better solutions). Semaphore is incremented each time an archive is opened. DLL Loading/Unloading code blocks until reaches zero.
All DLL loading/unloading? Remember we can't check if DLL uses serialization until we load it.
We're loading the DLL because we know apriori that it contains the code that implements serialization for a particular class.
So, you need to split each request in two parts: first the allows the server to determine which DLLs to load, and another one that gives the other data. You'd need to break connection between those two steps which does not look all the nice.
Again, the serialization library doesn't know which DLLS to load. It presumes that code is present for all registered/exported types. If such types are not registered or exported, an exception will be thrown. If you want to load the DLLS on the fly (somehow), youll have to communicate across the space/time which DLLS you want to see loaded before you start to serialize the types they implement. The serialization system has no map which implements (type -> name of DLL which serializes that type). If one feels this is necessary for his application, it would be made outside the serialization system itself.
And further: say you have a server that talks with 10 clients at the same time using some archive class. One client requests an operations that needs loading a DLL. Do you expect that:
1. Server will stop accepting new connections 2. Wait till 9 other connections stop 3. After that, load the DLL?
The serialization system requires that code to save/load types exist in both contexts. This is a fundamental limitation of the system. Its up to the user to decide if this limitation makes it unsuitable for his application. In practice, I would expect that in a system such as the above, all known types would be loaded before any data is transmitted.
or simply that all connection will be dropped?
What ever the library user want's to do.
I suppose that any use of My_class with simultaneous unloading of DLL that defines that class is so risky, that you should not take special care about this in serialization at all. If users unload DLL while instances of the class are still around, they already have a bug.
Agree. My example just showed one way that a library user could avoid such a bug.
BTW, on-demand loaded DLLs are not essential to this discussion. BOOST_CLASS_EXPORT becomes static object, right? C++ standard says that static initializer constructor can be executed right before the first function in some module is called. So, you can get unexpected BOOST_CLASS_EXPORT executions even without on-demand loaded DLL.
This is an interesting point. I believe that the situation is slightly different. In this case: void f(){ static X x; ... } The constructor for x is invoked the first time f() is called. In this case: class X { static X x; ... }; X X::x. The constructor X::x is invoked at pre-execution time. At least that's my understanding and it seems that all the compiler's in our test suite seem to support this behavior.
Again -- you read something from archive over network, and take some action. Accidentally, you call a function in new module and BOOST_CLASS_EXPORT is executed.
Again - I don't believe this could ever happen. The implementation of BOOST_CLASS_EXPORT depends on static constructors being executed at pre-execution time or for the case of DLLS - up DLL loading
Now, on Unix all static initialisers are run when the program is first loaded, so I probably should not care if some other users run into problems.
I don't believe this is a feature of the operating system but rather the compiler. I also believe that the serialization library presumes correctly that they will be invoked a pre-execution time. I never really thought of what happens when a DLL contains BOOST_CLASS_EXPORT, but it turns out only a little bit of extra work was required to remove some table entries when a DLL was unloaded. Robert Ramey