On 05/10/16 19:19, Marcos Douglas wrote:
Hi Tony,

On Wed, Oct 5, 2016 at 1:13 PM, Tony Whyman
<tony.why...@mccallumwhyman.com> wrote:
[...]

7. You are responsible for freeing the object that "provides" the delegated
interface.
But I'm working only using Interfaces. All variables are interfaces type.
So, I can't free the object myself.
As I understand it, it depends on the variable to which the object is first assigned. For example:

TMyClass = class(TInterfacedObject,IUnknown);

var Obj: TMyClass; {Note the var is of type TMyClass}
begin
  Obj := TMyClass.Create;
  try
   ...
  finally
    Obj.Free; {This is OK and necessary}
  end
end;

Alternatively:

var Obj: IUnknown;
begin
  Obj := TMyClass.Create;
  try
   ...
  finally
Obj.Free; {Not required and will cause an exception when obj goes out of scope}
  end
end;

Where do we go from here?
======================

Provided you understand what is happening then it works - but there is no
real documentation and it is really easy to get this wrong.
I disagree.
Well, works, but with memleaks... so, I can't have a real program on
the server with memleaks.
No, if you explicitly free the provider class there will be no memleaks. My point is that having to do this is counter-intuitive and easy to get wrong - or to overlook cases where it is necessary.

For me the consistent approach should be that when you coerce an interface
from an object, the reference count of the object that "provides" the
delegated interface is always the one that is incremented and the interface
remains tied to that object  An object that "is the source of" a delegated
interface should always have its lifetime tied to that of the object that
"provides" the delegated interface. i.e. it has an implicit reference to the
object that is the source of the interface.
I understood you but I can't help, because I don't know how the
compiler works to do this 'kind of magic' — I think only Object Pascal
has delegation in that way, right?
Here I was suggesting a compiler change (bug fix?)

Delegates is a powerful feature. I can write less and compose complexy
objects using delegation. Really cool.

We need to compare with Delphi?
I don't have it, but I guess this problem there isn't there.
I never used delegated interfaces in Delphi. In FPC I try to avoid them given the problems you get. On the other hand, reference counted com interfaces are a great feature and it's a pity delegated interfaces are so awkward.

What do you think?

Best regards,
Marcos Douglas

On Wed, Oct 5, 2016 at 1:13 PM, Tony Whyman
<tony.why...@mccallumwhyman.com> wrote:
On 05/10/16 16:26, Marcos Douglas wrote:
Tony Whyman had posted on August 10 a problem with the compiler using
Delegates.
He used a workaround to "solve" his problem and the thread died.

Marcos,

I believe I concluded that this could be a bug or feature. Either way it is
a Bear Trap waiting for the unwary programmer and it would be nice if in
some way the implementation could be improved. The problem, as I see it is:

Basics:

1. Whenever an interface reference is coerced from an interfaced object, the
object's reference count is incremented.

2. When the interface is copied that reference count is again incremented.

3. When the interface goes out of scope, the reference count is decremented
and when it reaches zero, the object is freed.

So far so good, but, when you have a delegated interface:

Terminalogy: In the example:

     TMyValue = class(TInterfacedObject,IValue);

     TMyObject = class (TinterfacedObject,IMyInterface)
     ...
     property Value: IValue read FValue implements IValue;
     end;

     Then a TMyValue object "is the source of" the delegated interface.
     A TMyObject object "provides" the delegated interface.

4. Whenever an interface reference to a delegated interfaced is coerced from
an interfaced object, it is the reference count of the object that "is the
source of" the delegated interface that is incremented.

5. When the interface is copied the reference count of the object that "is
the source of" the delegated interface is incremented.

6. When the interface goes out of scope, the reference count of the object
that "is the source of" the delegated interface is decremented and when it
reaches zero, that object is freed.

7. You are responsible for freeing the object that "provides" the delegated
interface.

To me this is counter-intuitive behaviour and this counter-intuitiveness is
compounded by the case where:

a. An interfaced object provides only a delegated interface.

b. An inherited interface (e.g. IUnknown) is coerced from the object.

In this case, the reference count incremented is that of the object that
"provides" the delegated interface  and not the object that "is the source
of" the delegated interface.

Where do we go from here?
======================

Provided you understand what is happening then it works - but there is no
real documentation and it is really easy to get this wrong.

For me the consistent approach should be that when you coerce an interface
from an object, the reference count of the object that "provides" the
delegated interface is always the one that is incremented and the interface
remains tied to that object  An object that "is the source of" a delegated
interface should always have its lifetime tied to that of the object that
"provides" the delegated interface. i.e. it has an implicit reference to the
object that is the source of the interface.

Tony Whyman
MWA

_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to