On Wed, 28 Nov 2012, luiz americo pereira camara wrote:
2012/11/28 Graeme Geldenhuys <gra...@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.
_______________________________________________
fpc-devel maillist - fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel