You are not logged in.
Arnaud, please take a look - is it possible add increase and decrease a RefCount of the created object before and after calling the OnServiceCreateInstance handler (mormot.soa.server unit, at the end of the TServiceFactoryServer.CreateInstance() method)?
from
if Assigned(fRestServer.OnServiceCreateInstance) then
fRestServer.OnServiceCreateInstance(self, result);
if AndIncreaseRefCount then
IInterface(result)._AddRef; // allow passing self to sub-methods
to
IInterface(result)._AddRef;
if Assigned(fRestServer.OnServiceCreateInstance) then
fRestServer.OnServiceCreateInstance(self, result);
dec(TInjectableObjectRest(result).fRefCount);
if AndIncreaseRefCount then
IInterface(result)._AddRef; // allow passing self to sub-methods
The difference in the lines 1 and 4 of this code block.
The problem is that when calling an OnServiceCreateInstance handler, the following happens:
- the instance of the created object passed to this method with a RefCount equal to 0;
- when trying in the OnServiceCreateInstance handler to check whether the passed object is implemented the specified interface (like "if supports (instance, isomeinterface, intfvar) then ..."), the object's RefCount increases by 1 and becomes equal to 1;
- when exiting from OnServiceCreateInstance handler, the object's RefCount decreases by 1 and becomes equal to 0;
- the object is destroyed;
- then in the last line of the TServiceFactoryServer.CreateInstance() method (IInterface (result) ._ addref) occurs AV, because the object is already destroyed.
If increase the object's RefCount by 1 before entering into the OnServiceCreateInstance handler, then the object will pass into the OnServiceCreateInStance handler with a RefCount equal to 1, then it will increase to 2, and then it will decrease to 1, and at the end the object will not be released.
After returning from OnServiceCreateInstance handler, the object's RefCount will be decreased to the initial value.
If in the OnServiceCreateInstance handler there will be no operations that change the value of the object's RefCount, then everything must also be good.
That is, I do not want to explicitly specify an object class, as in the example to the OnServiceCreateInstance (code is slightly changed):
procedure TAppSrvCore.RestSrvDB_OnCreateInstance(Sender: TServiceFactory; Instance: TInterfacedObject);
begin
if TServiceFactoryServer(Sender).ImplementationClass = TSomeService then
begin
...
TSomeService(Instance).DBConnection := Connection;
end;
end;
Instead, I want to use an interface that all the classes of services will implement, and in the OnServiceCreateInstance handler I will check whether the created object implements this interface:
procedure TAppSrvCore.RestSrvDB_OnCreateInstance(Sender: TServiceFactory; Instance: TInterfacedObject);
var
intf: ISomeService;
begin
if Supports(Instance, ISomeService, intf) then <-- inc RefCount
begin
...
intf.SetConnection(Connection);
end;
end; <-- dec RefCount
I tried to change the code in this way, and such approach is worked for me.
Maybe I did not consider something and this is something unsafe or incorrect?
Or is it in general a bad idea?
Offline
Why not just something like
inc(TInjectableObjectRest(result).fRefCount); // >0 within the event
if Assigned(fRestServer.OnServiceCreateInstance) then
fRestServer.OnServiceCreateInstance(self, result);
if not AndIncreaseRefCount then
dec(TInjectableObjectRest(result).fRefCount);
Please try https://github.com/synopse/mORMot2/comm … 1b8364e123
Offline
Good morning, Arnaud!
Thanks a lot, this feature works great
Last edited by L_VV (2021-03-30 08:25:05)
Offline