[fpc-devel] Considerations about observer [was: Free Pascal 2.6.2 rc1]

michael.vancanneyt at wisa.be michael.vancanneyt at wisa.be
Wed Nov 28 17:07:18 CET 2012



On Wed, 28 Nov 2012, luiz americo pereira camara wrote:

> 2012/11/28 Graeme Geldenhuys <graeme at geldenhuys.co.uk>:
>> On 2012-11-27 16:19, Michael Van Canneyt wrote:
>>>
>
>> If you haven't made other changes to those LCL Mediators since the code
>> you emailed me, I could take a look at updating the code for Lazarus too.
>>
>> That's a perfect example of the FPC Observers support being fully
>> functional as-is.
>>
>
> I don't discuss being fully functional as is. But you must agree that,
> if an architeture works in a scenario does not mean it's good or at
> least could not be improved.

Correct. 
But the design should also not try to cover all possible use cases at any cost.

Till now, I have not seen a common use case that will not work.

> I just proposed a change that will give more flexibility for the
> programmer when designing his application interface. As a plus with
> less typecasts, so less overhead.

If we assume for a second that the internal change to store the interface 
instead of the instance is done:

There are not less typecasts executed, they are in a different place simply.
You must always type the typecast before calling AttachObserver, I do it 
inside AttachObserver. 
My code is therefore simpler to read, generates less code and hence is preferable.

I'm not speaking idly about less code generated. Interfaces generate
some overhead. COM interfaces generate even quite some overhead.

Compare this (not meant to be runnable):

-----------------------------------------------------------------------
{$mode objfpc}
uses classes;

Procedure DoI(I : IInterface);

begin
   I._addref;
end;

Var
   C : TComponent;

begin
   DoI(C as IInterface);
end.
-----------------------------------------------------------------------

With this:

-----------------------------------------------------------------------
{$mode objfpc}
uses classes;

Procedure DoI(C : TComponent);

begin
   (C as IInterface)._addref;
end;

Var
   C : TComponent;

begin
   DoI(C);
end.
-----------------------------------------------------------------------

The latter (no interface passed on) generates the following assembler 
for the main program:

         movq    U_$P$PROGRAM_$$_C,%rdi
         call    P$PROGRAM_$$_DOI$TCOMPONENT

The former (pass an interface) generates for the main program the following assembler:

         movq    $0,-104(%rbp)
         leaq    -24(%rbp),%rdx
         leaq    -88(%rbp),%rsi
         movq    $1,%rdi
         call    FPC_PUSHEXCEPTADDR
         movq    %rax,%rdi
         call    FPC_SETJMP
         movq    %rax,-96(%rbp)
         testl   %eax,%eax
         jne     .Lj10
         movq    _$PROGRAM$_Ld1,%rdx
         movq    _$PROGRAM$_Ld1+8,%rcx
         movq    U_$P$PROGRAM_$$_C,%rsi
         leaq    -104(%rbp),%rdi
         call    fpc_class_as_intf
         movq    -104(%rbp),%rdi
         call    P$PROGRAM_$$_DOI$IUNKNOWN
.Lj10:
         call    FPC_POPADDRSTACK
         leaq    -104(%rbp),%rdi
         call    fpc_intf_decr_ref
         movq    -96(%rbp),%rax
         testq   %rax,%rax
         je      .Lj11
         call    FPC_RERAISE
.Lj11:

If you use corba interfaces, then the interface version of the main program is reduced to

         movq    $_$PROGRAM$_Ld1,%rsi
         movq    U_$P$PROGRAM_$$_C,%rdi
         call    fpc_class_as_corbaintf
         movq    %rax,%rdi
         call    P$PROGRAM_$$_DOI$MYI

This kind of code you will generate for each call to AttachObserver/DetachObserver.

So, not requiring the interface to be passed on saves code if you use corba interfaces. 
Using COM classes would generate even more code for each invokation.

Just to show why I prefer to avoid COM interfaces and the whole 'as' when possible.

If it had been possible to implement the whole observer thing without using
interfaces, I would have done it, but alas...

Michael.



More information about the fpc-devel mailing list