#1 2021-03-29 23:34:51

L_VV
Member
Registered: 2020-10-29
Posts: 38

Is it possible to change code around OnServiceCreateInstance call?

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

#2 2021-03-30 06:48:50

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Is it possible to change code around OnServiceCreateInstance call?

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

#3 2021-03-30 08:24:52

L_VV
Member
Registered: 2020-10-29
Posts: 38

Re: Is it possible to change code around OnServiceCreateInstance call?

Good morning, Arnaud!

Thanks a lot, this feature works great smile

Last edited by L_VV (2021-03-30 08:25:05)

Offline

Board footer

Powered by FluxBB