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

Reply via email to