All, Speaking honestly, I've got lost in ping ponging between different aspects of the topic. So feel free to correct me if I'll be going a completely wrong way. And please forgive me for writing the obvious things, as I tried to compose a complete picture for myself.
The basic requirement we have at hands is to provide full MT safety at the API level. And it was officially stated as a v2.5 feature, so there is no good reason to step back. Ideally, it should have handle destroying to be safe as well. One may claim that this requirement is non-natural and no sane program would be concurrently destroying the handle and working on that handle, but in fact v2.5 works exactly this way -- database and attachment shutdown is asynchronous and may interact with user API calls on the same handle -- and we have it working correctly. So it cannot be completely unexpected for user applications either, be it intentional or not, and a clever error message is surely better than a crash in this case. This requirement is quite easy to achieve with artificial handles like the ones we have prior to v3.0, but any indirect (vtable based) call won't work if the object behind that vtable gets destroyed in the meantime. All the discussion here goes around the fact that the vtable may be invalidated by a concurrent thread. In this case, I don't see any better solution than an explicit reference counting embedded into our API. It's well-known and it solves the problem. And I don't have much to add to the points already raised by Alex and Vlad. However, I see nobody looking from the other side. Why should vtable become broken once the object gets destroyed? It's surely unavoidable if the object is inherited from the returned interface. But does it really have to be so? Imagine a proxy object implementing the returned interface, referencing the dynamic object via an embedded pointer, but allocated out of the global pool and being reused instead of destroyed/recreated. In this case the vtable calls will work always and the actual object can be validated inside like we do now, so the API calls will be returning a proper error (at least until the proxy object gets reused -- but it could be delayed under some rules). I don't say this is a better approach, just something to be mentioned for the sake of completeness. Regarding the other points. As for the y-valve <-> provider interaction, the good (IMNSHO) solution would be the one that does not require the provider to know about its caller. In other words, it may call the y-valve forward to initiate new objects (e.g. to have an external database access) but should not call it back to deal with existing objects (e.g. itself) except calling the hooks passed as parameters. I believe some form of queryInterface/upgradeInterface is required in the API. But I don't think we should mimic IUnknown precisely without really strong reasons. First of all, we don't need GUIDs as interface version identifiers, as our objects are limited to Firebird only usage. And if Delphi is the only reason to be binary compatible with IUnknown, then I'm against it. Times change and now I'd pay more attention to Java/.NET along with Python/PHP/whatever than think how to please those poor Delphi users ;-) Now I'm shutting up and letting you to argue. I've undoubtedly missed something. Dmitry ------------------------------------------------------------------------------ Xperia(TM) PLAY It's a major breakthrough. An authentic gaming smartphone on the nation's most reliable network. And it wants your games. http://p.sf.net/sfu/verizon-sfdev Firebird-Devel mailing list, web interface at https://lists.sourceforge.net/lists/listinfo/firebird-devel