
Robert Ramey wrote:
Vladimir Prus wrote:
I think you're going contrary to the basic threading assumption in the C++. If I explicitly use the same object from two different threads, I must use locking myself.
This is what I disagree with. I don't any problem with multiple threads accessing the same data structures as long as the accesses are read-only and the structures are not being modified.
If, for all appearence, I don't use the same object in two threads, but there's some *internal* shared data structure, it should be protected *internally*. In this case, there's some internal serialization table that I know nothing about, so it should be protected by serialization library.
Repeat, I don't think this is necessary.
Dave has already commented on this point: if the structures are modified by some thread, you need locking.
Besides, I don't understand how you can "inhibit loading of DLLS". Say, one thread has created an archive and does something with it. Some other thread tries to open DLL. What should happen? Should that other thread get "sorry, some archives are open" error? And what will it do?
A couple of possibilities. It could somehow check to see that no archives are open. (The serialization library might have to add support for this). It could throw an exception if an attempt is made to change a global structure when when an archive is open.
Wait until the other thread is done with archive? And what if the other thread uses archive to talk over network and will never close the achrive? And even if it will close archive, how will the other thread wait for that? There's no public method that tells that any archive is open.
Correct, but this could be remedied without dragging threads in to it.
Okay, but then assume the following scenario: 1. A program creates an archive to read from network connection. Network connection is never to be closed. 2. A command arrives via connection that requires loading a plugin. 3. The plugin has BOOST_CLASS_EXPORT, so attempt to load it crashes. We have two possibilities: 3a. Since the exception happens when you modified serialization tables, and that happens in static initializer, you cannot catch the exception anywhere in the plugin code. Since the plugin (on Unix), is opened with C function dlopen, it's not clear if the exception will propagated across that C function. So, the whole application might crash. 3b. Assume we checked if archives are opened before calling dlopen. Actually, we cannot, because we don't know, generally speaking, if the plugin uses BOOST_CLASS_EXPORT or not. But assume we somehow know this and figured that we can't load the plugin. Now: - we can't close the network connection, because it waits for further commands - we can't load plugin because some archive is opened, so we can do the previous command we've received Neither alternative looks particularly attractive to me.
There's another aspect here. The code for serialization presumes that the global tables are static during the lifetime of the archive. For example, as a particular item is serialized, its class identifier is saved in an archive specific table. Thus the save code used the object identifier to invoke the save method for the specific class. Same goes for the load side. Now, if the global table changes while an archive is open, all bets are off because the save/load code may not be around anymore. So.
a) global tables can't be changed while an archive is open an still expect the system to function.
This is over-generalisation. Clearly, new BOOST_CLASS_EXPORT statements won't break anything.
b) thus DLLS should be loaded/unloaded only when there are no archives open.
It's only disallowed to save/load objects that come from DLL and registered in global id table for which the corresponding DLL is unloaded. What this means is that ids should be removed from global table on DLL unload -- I think this can be done by implementing a destructor in the same helper classes that registers id in its constructor.
c) respecting this rule is the responsability of the calling program.
As I've shown above, it's not always possible to respect this rule.
While we're at it, I would also like to consider enforcing a rule that there can be at most one instance of serialization code for a specific type existing at one time.
What do you mean? If there are two DLL defining the same function but with different bodies, that's ODR violation. If they define the same function with the same body, that's no problem. - Volodya