Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-11-10 Thread Martin Schreiber
On Friday 11 November 2016 07:48:54 Lars wrote:
> On Thu, November 10, 2016 11:04 pm, Martin Schreiber wrote:
> > On Friday 11 November 2016 04:21:31 Lars wrote:
> >> Replying to an old thread in my inbox. Apologies if it's obsolete as it
> >> is a month old.
> >
> > I don't think such themes are allowed in fpc-pascal.
>
> If an oberon like garbage collector, instead of reference counting, could
> be somehow implemented into fpc, then it's still on topic.
>
> However, oberon garbage collector is likely to alien to apply to fpc.
> I just wonder, since fpc is based on Wirth's work, if any fpc developers
> have looked into how oberon does garbage collection, and applied this
> knowledge to fpc. I tried to keep it as much on topic, in that sense - but
> I understand it's not 100 percent fpc (as it currently stands) related.

True, but my possible answers probably are below the tolerated level. ;-)

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


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-11-10 Thread Lars
On Thu, November 10, 2016 11:04 pm, Martin Schreiber wrote:
> On Friday 11 November 2016 04:21:31 Lars wrote:
>
>>
>> Replying to an old thread in my inbox. Apologies if it's obsolete as it
>> is a month old.
>>
> I don't think such themes are allowed in fpc-pascal.

If an oberon like garbage collector, instead of reference counting, could
be somehow implemented into fpc, then it's still on topic.

However, oberon garbage collector is likely to alien to apply to fpc.
I just wonder, since fpc is based on Wirth's work, if any fpc developers
have looked into how oberon does garbage collection, and applied this
knowledge to fpc. I tried to keep it as much on topic, in that sense - but
I understand it's not 100 percent fpc (as it currently stands) related.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-11-10 Thread Martin Schreiber
On Friday 11 November 2016 04:21:31 Lars wrote:
>
> Replying to an old thread in my inbox. Apologies if it's obsolete as it is
> a month old.
>
I don't think such themes are allowed in fpc-pascal. Please continue the 
discussion on MSEide+MSEgui mailinglist:
https://lists.sourceforge.net/lists/listinfo/mseide-msegui-talk
Archive:
https://www.mail-archive.com/mseide-msegui-talk@lists.sourceforge.net/

Thanks, 
Martin
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-11-10 Thread Lars
On Wed, October 5, 2016 9:54 pm, Martin Schreiber wrote:
> On Thursday 06 October 2016 00:16:22 Tony Whyman wrote:
>
>> On 05/10/16 23:03, Graeme Geldenhuys wrote:
>>
>>> Martin Schreiber recently mentioned in another Interface discussion
>>> that there is a very good reason he doesn’t use COM style
>>> interfaces… Reference Counting!
>>>
>>
>> Used properly reference counted interfaces are very powerful and allow
>> for some very elegant programming. Do you complain about AnsiStrings?
>> They are reference counted. Would you really want to have to free every
>>  string explicitly? Dynamic arrays are similarly reference counted.
>>
> Reference counting is great for simple types like strings and dynamic
> arrays but is a nightmare with the venturesome mixture of COM-interface
> and classes from Delphi. Even reference counting for complex classes is no
> good idea IMO, I fear the times when FPC will implement ARC.
> I don't think that a programming language should hide more and more of the
>  internal working of the code he writes from the programmer. Take a look
> at the modern C++ programs; the LLVM-compiler is a good example. It is
> horrific slow. Stepping through the code shows that there are complex
> multi-level dynamic type conversion and dataaccess routines at almost
> every statement. The typical C++ programmer does not need to care about
> because the programming language takes care for the boring tasks. The
> typical C++ programmer actually *does* not care about performance because
> competing programs are not faster; they are written in a modern
> programming language too... Recently I had to revive my stone old AMD-K6 PC
> with Windows 95. What marvel, that relict with its age-old applications
> provides a better user experience, is snappier, more convenient and more
> productive than my newest Linux machine with the modern desktops and
> applications.
>
> Martin

Replying to an old thread in my inbox. Apologies if it's obsolete as it is
a month old.

Martin, as you know, Windows 95 is mostly coded in plain C, so guess what
that meant: you had to reboot your pc every day to reset all the memory
leaks. So your idea that we should not be hiding code with more
abstraction layers is a double edged sword. Windows 95 is a very zippy,
fast, snappy operating system. But it also was not garbage collected so
had memory leaks due to poor programming in plain C.  Remember when people
migrated over to Windows 2000 and Windows XP and found that they no longer
needed to restart their PC daily to reset the memory leaks?

 Sometimes my windows 98 computer would last for a week, and that was
about it before I had to restart. Usually I had to restart every 1-3
days. And why is that? Because windows 95/98 did not have an abstract
programming language in place which hid details. It's all manual memory
management which causes tons of bugs. And these bugs are the same issue
seen in all kinds of delphi/lazarus apps

Admitting, however, that Windows 2000 and XP did not migrate to any
garbage collected language, they just improved the old buggy code so that
there were less memory leaks and now instead of rebooting your PC every
day or 3 days, you can wait a month before rebooting, or sometimes a
couple weeks, or sometimes a week. But there are still bugs in
win2000/windows10/windows7 which cause me having to reboot my PC.  And
wow, Firefox needs to be constantly restarted, as the memory leaks grow
out of control. But that's not a plain C app.

At the same time, I'm also scared of reference counting as you are, for
classes, as garbage collection mechanism. But since you are against hiding
details from the programmer, what's your opinion of Oberon garbage
collection that Wirth designed, if it was somehow implemented in FPC?
Likely that won't happen. However you say you are against hiding too many
details from the programmer (abstraction) so you think Oberon's garbage
collection system is too high level and would prefer to free and create?

To keep it on topic, related to fpc, and to not divert to oberon
discussion only: are you saying that if somehow and oberon like garbage
collection was implmented in fpc you'd be against that as it is too
abstract, or are you saying you are just against reference counting, but
would accept an Oberon like garbage collection? Unfortunately, that means
more like a new programming language rather that continuing fpc as it is,
likely. As oberon is designed to be that way, to handle garbage collection
and even module unloading/loading at run time, whereas fpc not so much.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread stdreamer

On 07/10/2016 18:33 μμ, Marcos Douglas wrote:

We don't need "clean up properly" instances that is interface-based.
If this solve the problem for contained objects, I'll do it!
BUT, if I do this I can forget all about  TContainedObject or
TAggregatedObject? If I can't, this not make sense.


OK this needs a bit more information.

The interface variable is only a half measure. It assumes and expects 
that the container (the object that has a delegation) will always get 
destroyed after all references to the delegated interface are released. 
It does not check for it and it leaves everything to the programmer. If 
the contained interface needs the container to function properly then a 
number of of exception will be raised as soon as the container gets freed.
The TContainedObject on the other hand makes sure that the container can 
not be destroy as long as there are references on the contained 
interface which is a much safer solution.


I have used both with success in the past I still prefer the 
TContainedObject approach for this little extra piece of mind that it 
provides me.


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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread stdreamer

On 07/10/2016 18:33 μμ, Marcos Douglas wrote:

The problem is: The user (programmer) needs to know (previously) if
such classes can or not be used as a contained object!


True then again that is true for all objects not only interfaces. You 
need to understand what they address how they address it and what are 
their short comings to use them to their full extend.



We don't need "clean up properly" instances that is interface-based.
If this solve the problem for contained objects, I'll do it!
BUT, if I do this I can forget all about  TContainedObject or
TAggregatedObject? If I can't, this not make sense.



Well this makes me think that you do not understand the difference 
between heap based and stack based variables. You do understand that a 
variable on the heap never goes out of scope, which makes automatically 
decreasing the reference counter impossible, right? You have to nil it 
manually and this is true in C++ as well.



"...to a language feature that has nothing to do with it."
Your opinion.


I wish.


I've been using COM Interfaces (ref-counting) for years without
problems of memory leaks.
I just want to use the feature "delegation". That's it. But the design
of this solution looks wrong. Not only in FPC, but Delphi too — as
said Graeme.
The documentation recommends nothing about TContainedObject or
TAggregatedObject on topic about Delegates.


of course not, contained objects is one solution it can be reversed as 
well ee the contained object is in fact the object that used the 
delegate and depending on the design it can be passed as parameter in 
the constructor or changed through the property to something else that 
is not contained at all. It so happens that you are using the contained 
object logic.


To be clear I have no objection in mentioning the pitfalls in the 
documentation and show the tcontainedobject as a possible solution to 
the problem.



IMHO this is a problem. You guess not, but you just know a workaround.

There is a design problem. Maybe there is no solution. Maybe is so
hard to fix that don't worth. I don't know... but there is a problem.
It's a fact.


I disagree the use of "fact" in this context is wrong but hey what ever 
floats your boat.



If somebody says: "You should know these classes..." or "you should
know what you're doing..."
I will answer: this is not about OOP, just procedural. OOP is about
encapsulation. If I need to see the class' code, this means that it
was not well done.


No! Any object solves a single problem. If it does not fit in your own
design then you either have the wrong design or you need to customize the
object to include your use case. In both cases you need to read up and
understand which use cases is solving, how it does it and how you can extend
it to support your own use cases. It is not responsible to accommodate your
assumptions.


So, if I understood right, you saying that:
If I have a function that expects an IStream interface as argument, I
can't pass any class that implements that interface BEFORE see which
hierarchy it belongs? If I will can use as "contained", "aggregated"
or just "stand alone"?


That is a use case and no I never said that your use cases are wrong 
invalid or improper.



Can things get better? Sure every change no matter of its size, moves the
library forward but if that change is appropriate for the library can only
be decided by the library maintainers and you (or me for that matter) crying
wolf does not help.


So, I can change the hierarchy of my classes and break the whole project?
Is it correct and makes sense for you?
I truly know that is not about encapsulation or about object-oriented
programming.


I have to question a design that changing a single inheritance breaks 
the library. If this is such a big problem then don't change your 
hierarchy make sure that you are properly setting all interfaces in the 
heap to nil when you are finished using them and forget about everything 
else.


Or go the opposite route create an IContained interface that 
encapsulates the code in TContainedObject  and tell your team that you 
can use any class that implements IContained as a delegate.


There are a lot of designs to pick from and every one has its pros and 
cons pick one that fits in your design.




For me extending the TContainedObject to support both contained and stand
alone use is trivial I bet you can do it as well now that you know where to
look.


That is a good idea.

If is possible. If doesn't have any "compiler magic" inside this
classes, I will do it.
Better. I will copy the implementation of these classes to create my
own implementations.


That's the spirit use the library to your advantage and if you have the 
time, inclination and will, post a proposition for a new class giving 
the use cases it addresses.



I'm against adding that kind of functionality to TContainedObject as
it is outside of its designed goal.


I agree...


If a new object adds more value or more bloat to the library

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread Marcos Douglas
On Fri, Oct 7, 2016 at 12:33 PM, Marcos Douglas  wrote:
>> For me extending the TContainedObject to support both contained and stand
>> alone use is trivial I bet you can do it as well now that you know where to
>> look.
>
> That is a good idea.
>
> If is possible. If doesn't have any "compiler magic" inside this
> classes, I will do it.
> Better. I will copy the implementation of these classes to create my
> own implementations.

I seen now (D7source). It looks pretty simple.

The TAggregatedObject has this attribute:
FController: Pointer;  // weak reference to controller

:)

This is a workaround. I need to do another one.
That's Okay because everything is going to be encapsulated in
TAggregatedObject (or in another new class) and for the users
(programmers) that will be transparent.

@stdreamer
Anyway, thank you for the advice about this class.

Best regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread Marcos Douglas
On Fri, Oct 7, 2016 at 11:46 AM, stdreamer  wrote:
> On 07/10/2016 16:12 μμ, Marcos Douglas wrote:
>>
>> The team shouldn't know about the hierarchy; about how was implemented
>> these classes.
>> They can use TDataStream directly or as a contained object.
>> But as I understood, we need to use TContainedObject or
>> TAggregatedObject only in these "special cases"
>
> You are correct the TContainedObject can only be used with a root object,
> now what? Is this a block for you?

Of course! As I explained before.

> It is not the library's responsibility to solve your problems only to
> assist. TContainedObject is a basic solution which is generic enough to
> accommodate 90% (assumed number just to emphasize its usefulness) of the use
> cases.
> Now why is your use case special enough to be included in the library it
> self?

The problem is: The user (programmer) needs to know (previously) if
such classes can or not be used as a contained object!

>> I didn't test yet. I will. But if I'm right, ie, if TDataStream is
>> inherited from TContainedObject and, because that, I can not use
>> TDataStream as a simple instance, without a "root" object... well,
>> this design is wrong.
>
>
> well let me see
> You failed to clean up properly after your code (a simple fValue := nil in
> TMyApp.Destroy method should solve all your problems),

We don't need "clean up properly" instances that is interface-based.
If this solve the problem for contained objects, I'll do it!
BUT, if I do this I can forget all about  TContainedObject or
TAggregatedObject? If I can't, this not make sense.

>... you did not knew the
> basic mechanisms provided for the exact problem you are having and you
> attached your design sort comings to a language feature that has nothing to
> do with it. All in all, you have failed to do your homework. I should listen
> to your opinion about design . why exactly?

"...to a language feature that has nothing to do with it."
Your opinion.

I've been using COM Interfaces (ref-counting) for years without
problems of memory leaks.
I just want to use the feature "delegation". That's it. But the design
of this solution looks wrong. Not only in FPC, but Delphi too — as
said Graeme.
The documentation recommends nothing about TContainedObject or
TAggregatedObject on topic about Delegates.

IMHO this is a problem. You guess not, but you just know a workaround.

There is a design problem. Maybe there is no solution. Maybe is so
hard to fix that don't worth. I don't know... but there is a problem.
It's a fact.

>> If somebody says: "You should know these classes..." or "you should
>> know what you're doing..."
>> I will answer: this is not about OOP, just procedural. OOP is about
>> encapsulation. If I need to see the class' code, this means that it
>> was not well done.
>>
> No! Any object solves a single problem. If it does not fit in your own
> design then you either have the wrong design or you need to customize the
> object to include your use case. In both cases you need to read up and
> understand which use cases is solving, how it does it and how you can extend
> it to support your own use cases. It is not responsible to accommodate your
> assumptions.

So, if I understood right, you saying that:
If I have a function that expects an IStream interface as argument, I
can't pass any class that implements that interface BEFORE see which
hierarchy it belongs? If I will can use as "contained", "aggregated"
or just "stand alone"?

> Can things get better? Sure every change no matter of its size, moves the
> library forward but if that change is appropriate for the library can only
> be decided by the library maintainers and you (or me for that matter) crying
> wolf does not help.

So, I can change the hierarchy of my classes and break the whole project?
Is it correct and makes sense for you?
I truly know that is not about encapsulation or about object-oriented
programming.

> For me extending the TContainedObject to support both contained and stand
> alone use is trivial I bet you can do it as well now that you know where to
> look.

That is a good idea.

If is possible. If doesn't have any "compiler magic" inside this
classes, I will do it.
Better. I will copy the implementation of these classes to create my
own implementations.

> I'm against adding that kind of functionality to TContainedObject as
> it is outside of its designed goal.

I agree...

> If a new object adds more value or more bloat to the library is up to the
> maintainers to decide.

...but IMHO, it would be a better design if these classes do not exist
for this purpose.

Best regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread Marcos Douglas
On Fri, Oct 7, 2016 at 11:02 AM, Tony Whyman
 wrote:
> ...As a workaround for the interface delegation problem it works, as long as
> you don't try and use TDelegateClass on its own

As I said... sad.

Regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread stdreamer

On 07/10/2016 16:12 μμ, Marcos Douglas wrote:

The team shouldn't know about the hierarchy; about how was implemented
these classes.
They can use TDataStream directly or as a contained object.
But as I understood, we need to use TContainedObject or
TAggregatedObject only in these "special cases"
You are correct the TContainedObject can only be used with a root 
object, now what? Is this a block for you?


It is not the library's responsibility to solve your problems only to 
assist. TContainedObject is a basic solution which is generic enough to 
accommodate 90% (assumed number just to emphasize its usefulness) of the 
use cases.
Now why is your use case special enough to be included in the library it 
self?



I didn't test yet. I will. But if I'm right, ie, if TDataStream is
inherited from TContainedObject and, because that, I can not use
TDataStream as a simple instance, without a "root" object... well,
this design is wrong.


well let me see
You failed to clean up properly after your code (a simple fValue := nil 
in TMyApp.Destroy method should solve all your problems), you did not 
knew the basic mechanisms provided for the exact problem you are having 
and you attached your design sort comings to a language feature that has 
nothing to do with it. All in all, you have failed to do your homework. 
I should listen to your opinion about design . why exactly?



If somebody says: "You should know these classes..." or "you should
know what you're doing..."
I will answer: this is not about OOP, just procedural. OOP is about
encapsulation. If I need to see the class' code, this means that it
was not well done.

No! Any object solves a single problem. If it does not fit in your own 
design then you either have the wrong design or you need to customize 
the object to include your use case. In both cases you need to read up 
and understand which use cases is solving, how it does it and how you 
can extend it to support your own use cases. It is not responsible to 
accommodate your assumptions.


Can things get better? Sure every change no matter of its size, moves 
the library forward but if that change is appropriate for the library 
can only be decided by the library maintainers and you (or me for that 
matter) crying wolf does not help.


For me extending the TContainedObject to support both contained and 
stand alone use is trivial I bet you can do it as well now that you know 
where to look. I'm against adding that kind of functionality to 
TContainedObject as it is outside of its designed goal.
If a new object adds more value or more bloat to the library is up to 
the maintainers to decide.


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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread Tony Whyman

On 07/10/16 12:29, stdreamer wrote:
No! Delegation is a mechanism, when used, you have to know exactly how 
it works. Delegation is only used to minimize code instead of writing 
a bunch of procedures that call the contained object's methods. That's 
it and nothing more.


I believe that I now understand the issues around interface delegation 
and how to use it. You are correct, it's only an optimisation - and it 
sucks. I would never recommend anyone to use interface delegation as you 
have to only put a "foot wrong" and can end up memory leaks on one side, 
or access violations on the other. Writing a "bunch of procedures" may 
be tedious but it's less work in the end.

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


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread Tony Whyman

On 07/10/16 12:29, stdreamer wrote:
The point is that you are trying to equate delegation with contained 
objects/interfaces and that is not what delegates are about. 
Delegation has nothing to do with the underlined mechanism you choose 
to use. 


Hmm, not so sure about that. I have updated my original example from 
August to use TContainedObject (see below). As a workaround for the 
interface delegation problem it works, as long as you don't try and use 
TDelegateClass on its own. This is because although it appears as a 
reference counted com interface, it still relies upon another object to 
free it. The example returns:


Creating TDelegateClass
Creating TMyClass
Creating TDelegateClass
Destroying TMyClass
Destroying TDelegateClass

i.e. there is a missing call to the TDelegateClass destructor. This is 
because I created it standalone (in "DoRun) just to illustrate the point.


There is a real need to update the FPC manual to include 
TContainedObject. It's importance for interface delegation and its 
limitations. How you implement interface delegation clearly has a big 
outcome on how the interface is used by the user.


program project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, SysUtils, CustApp
  { you can add units after this };

type

  { TDelegateTest }

  TDelegateTest = class(TCustomApplication)
  protected
procedure DoRun; override;
  public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure WriteHelp; virtual;
  end;

  IMyInterface = interface
 procedure P1;
   end;

  { TDelegateClass }

   TDelegateClass = class(TContainedObject, IMyInterface)
   private
 procedure P1;
   public
 constructor Create(aController: IUnknown);
 destructor Destroy; override;
   end;

   { TMyClass }

   TMyClass = class(TInterfacedObject, IMyInterface)
   private
 FMyInterface: TDelegateClass;
 property MyInterface: TDelegateClass
   read FMyInterface implements IMyInterface;
   public
 constructor Create;
 destructor Destroy; override;
   end;

{ TDelegateClass }

procedure TDelegateClass.P1;
begin
  writeln('P1');
end;

constructor TDelegateClass.Create(aController: IUnknown);
begin
  inherited Create(aController);
  writeln('Creating ',ClassName);
end;

destructor TDelegateClass.Destroy;
begin
  writeln('Destroying ',ClassName);
  inherited Destroy;
end;

{ TMyClass }

constructor TMyClass.Create;
begin
  inherited Create;
  FMyInterface := TDelegateClass.Create(self);
  writeln('Creating ',ClassName);
end;

destructor TMyClass.Destroy;
begin
  writeln('Destroying ',ClassName);
  if FMyInterface <> nil then FMyInterface.Free;
  inherited Destroy;
end;

{ TDelegateTest }

procedure TDelegateTest.DoRun;
var Intf: IUnknown;
Intf2: IMyInterface;
begin
   Intf := TMyClass.Create;
   Intf2 := TDelegateClass.Create(Intf); {never destroyed}
  // stop program loop
  Terminate;
end;

constructor TDelegateTest.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  StopOnException := True;
end;

destructor TDelegateTest.Destroy;
begin
  inherited Destroy;
end;

procedure TDelegateTest.WriteHelp;
begin
  { add your help code here }
  writeln('Usage: ', ExeName, ' -h');
end;

var
  Application: TDelegateTest;
begin
  Application := TDelegateTest.Create(nil);
  Application.Title := 'Interface Delegation Test';
  Application.Run;
  Application.Free;
end.

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


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread Marcos Douglas
On Fri, Oct 7, 2016 at 8:29 AM, stdreamer  wrote:
> No! Delegation is a mechanism, when used, you have to know exactly how it
> works.

The "mechanism" here is about using [implements].
We have to know what is the sintaxe:
- declare a property
- use [implements] keyword
- could be a class or interface
- and so on.

The user (programmer) that consumes these classes as a contained
objects, should't know NOTHING about their hierarchies!

> Delegation is only used to minimize code instead of writing a bunch
> of procedures that call the contained object's methods. That's it and
> nothing more.

And this is great! As I know, only Object Pascal have this feature so,
let's use it.

> [...]
>
> The point is that you are trying to equate delegation with contained
> objects/interfaces and that is not what delegates are about. Delegation has
> nothing to do with the underlined mechanism you choose to use.
>
> Having said that, I have to agree with you that contained objects are the
> most common supporting mechanism for a delegation and probably the most
> logical to use.

Delegates is about: pass the work for another. That's it.
I can do that using only classical object composition. But Object
Pascal have this cool feature that I can write less and the design is
really good.
So, I would like to use it. But if I need to know everty
implementation for all my classes, to know if I can or not use as a
"contained" or "aggregate" object... this is wrong.

> As I said I do not see a rabbit hole that it was created by the compiler or
> the language nor I think that the compiler should constrain you to one
> mechanism.

Really?

Best regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread Marcos Douglas
On Fri, Oct 7, 2016 at 6:49 AM, Tony Whyman
 wrote:
> The problem being referred to is the functionality described here:
>
> http://freepascal.org/docs-html/current/ref/refse44.html#x98-127.4
>
> under the title "Interface delegation". The word "contained" does not appear
> here. Maybe it should, but it doesn't. If TContainedObject does indeed solve
> the problem then it would be useful to have it documented and, if so, for
> interface delegation using a TInterfacedObject subclass to be at least
> deprecated and may be even barred.
>
> The problem is that this is Rabbit Hole and it needs filling in otherwise
> more will fall down it.

In a Facebook group, called Delphi developer, Michal Mutl says:
Also you can implement TIntegerValue as TIntegerValue =
class(TAggregatedObject, IValue) and you can really take advantage of
ARC (no Free call in TMyApp Destroy impl). But then you must use it
only as delegate, not standalone (ExecuteIntegerValue will fail).

I didn't know about TContainedObject or TAggregatedObject... these
classes solve the problem? Maybe. But not so fast.

I've implemeted a Lib and I would like to say to my team:
— If you needs to implements an IStream interface, you can use
delegates, just use the TDataStream class.

The team shouldn't know about the hierarchy; about how was implemented
these classes.
They can use TDataStream directly or as a contained object.
But as I understood, we need to use TContainedObject or
TAggregatedObject only in these "special cases"

I didn't test yet. I will. But if I'm right, ie, if TDataStream is
inherited from TContainedObject and, because that, I can not use
TDataStream as a simple instance, without a "root" object... well,
this design is wrong.

If somebody says: "You should know these classes..." or "you should
know what you're doing..."
I will answer: this is not about OOP, just procedural. OOP is about
encapsulation. If I need to see the class' code, this means that it
was not well done.

Best regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread Marcos Douglas
On Fri, Oct 7, 2016 at 7:30 AM, Tony Whyman
 wrote:
> Reference Counted interfaces must be easy to use and should not require the
> user to have advanced knowledge of how they work. If that last point is true
> then all the that nay-sayers that argue against reference counted interfaces
> have their point made for them.

+1

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


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread Marcos Douglas
On Fri, Oct 7, 2016 at 6:31 AM, stdreamer  wrote:
>
> Τhe problem of a contained interface has already been solved, see the
> TContainedObject. To sum it up a contained object reference counting
> mechanism increments and decrements the container's reference counter it
> does not have a life of its own

Nobody tell about TContainedObject until now...
Maybe it should be documented on topic about delegates.

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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread stdreamer

On 07/10/2016 13:30 μμ, Tony Whyman wrote:

On 07/10/16 11:08, stdreamer wrote:

I see no rabbit hole or any other problem in the code posted so far
except perhaps lack of proper clean up which might be intentional.

A Rabbit Hole is not the same as a bug and my point is not that
"interface delegation" does not work, it is that it is counter-intuitive
and poorly documented to the point of undocumented. Your introduction of
TContainedObject is just another example of missing information.


No! Delegation is a mechanism, when used, you have to know exactly how 
it works. Delegation is only used to minimize code instead of writing a 
bunch of procedures that call the contained object's methods. That's it 
and nothing more.


The contained object is something else that happens to be used in this 
example. Here is an other delegation with out a contained interface.


interface
  TMyInteger = Class;

  IValue = interface
  ['{72D8B44F-5834-425D-AB3A-45785E94E2E4}']
function AsString:string;
  end;

  IMyInterface = interface
   ['{5E04F587-E4A0-42A7-850C-74C882BB5958}']
   procedure DoSomething;
  end;

  //tmyvalue can inherit from tContainedobject
  //for simplification.

  TMyValue = class(TInterfacedObject, IValue)
  private
FSource :TMyInteger;
  public
function AsString:String;
constructor Create(aSource:TMyObject);
  end;
  //IValue must be part of TMyObject not a simple property.

  { TMyObject }

  { TMyInteger }

  TMyInteger = class(TInterfacedObject, IMyInterface, IValue)
  private
FMyValue :variant;
function GetValue :IValue;
  private
property MyValue :IValue read GetValue implements IValue;
  public
procedure DoSomething;
  end;

implementation

function TMyInteger.GetValue :IValue;
begin
  Result := TMyValue.Create(Self);
end;

procedure TMyInteger.DoSomething;
begin

end;

function TMyValue.AsString :String;
begin
  result := ToString(FSource.FMyValue);
end;

constructor TMyValue.Create(aSource :TMyInteger);
begin
  inherited;
  FSource := aSource;
end;



Reference Counted interfaces must be easy to use and should not require
the user to have advanced knowledge of how they work.If that last point
is true then all the that nay-sayers that argue against reference
counted interfaces have their point made for them.

Erm knifes are easy to use as well but cutting your self with one is 
your problem to solve.


The point is that you are trying to equate delegation with contained 
objects/interfaces and that is not what delegates are about. Delegation 
has nothing to do with the underlined mechanism you choose to use.


Having said that, I have to agree with you that contained objects are 
the most common supporting mechanism for a delegation and probably the 
most logical to use.


As I said I do not see a rabbit hole that it was created by the compiler 
or the language nor I think that the compiler should constrain you to 
one mechanism.



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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread Tony Whyman

On 07/10/16 11:08, stdreamer wrote:
I see no rabbit hole or any other problem in the code posted so far 
except perhaps lack of proper clean up which might be intentional. 
A Rabbit Hole is not the same as a bug and my point is not that 
"interface delegation" does not work, it is that it is counter-intuitive 
and poorly documented to the point of undocumented. Your introduction of 
TContainedObject is just another example of missing information.


Reference Counted interfaces must be easy to use and should not require 
the user to have advanced knowledge of how they work. If that last point 
is true then all the that nay-sayers that argue against reference 
counted interfaces have their point made for them.


A Rabbit Hole comes from Alice in Wonderland and when you fall down it 
you are not just chasing a White Rabbit, you have found yourself in 
another universe that has a different logic to your own. Reference 
counting with Interface Delegation seems to have a different logic to 
that of normal reference counted interfaces - and that is why you feel 
that you have fallen down a Rabbit Hole as soon as you start trying to 
use them.


“But I don’t want to go among mad people," Alice remarked.
"Oh, you can’t help that," said the Cat: "we’re all mad here. I’m mad. 
You’re mad."

"How do you know I’m mad?" said Alice.
"You must be," said the Cat, "or you wouldn’t have come here.”
― Lewis Carroll, Alice in Wonderland
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread stdreamer

On 07/10/2016 12:49 μμ, Tony Whyman wrote:

You seem to be playing around with words. Perhaps I am guilty of sloppy
English when I say "interface is copied" when meaning "an interface
reference is copied". However, this does not change the underlying problem.
The problem being referred to is the functionality described here:

http://freepascal.org/docs-html/current/ref/refse44.html#x98-127.4

under the title "Interface delegation". The word "contained" does not
appear here.


As it should, contained interfaces are one way to solve the problem 
there are other ways that are design/domain specific and yet again there 
is the option(already given here) to use interface variables instead of 
object variables, just make sure you set them to null on the destructor 
to release the interface.


I see no rabbit hole or any other problem in the code posted so far 
except perhaps lack of proper clean up which might be intentional.



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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread Tony Whyman
You seem to be playing around with words. Perhaps I am guilty of sloppy 
English when I say "interface is copied" when meaning "an interface 
reference is copied". However, this does not change the underlying problem.


The problem being referred to is the functionality described here:

http://freepascal.org/docs-html/current/ref/refse44.html#x98-127.4

under the title "Interface delegation". The word "contained" does not 
appear here. Maybe it should, but it doesn't. If TContainedObject does 
indeed solve the problem then it would be useful to have it documented 
and, if so, for interface delegation using a TInterfacedObject subclass 
to be at least deprecated and may be even barred.


The problem is that this is Rabbit Hole and it needs filling in 
otherwise more will fall down it.



On 07/10/16 10:31, stdreamer wrote:

On 05/10/2016 19:13 μμ, Tony Whyman wrote:

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.
I'm guessing that by "coerced" you mean "reference a contained 
interface".


2. When the interface is copied that reference count is again 
incremented.
Interface can not be copied only implement objects can be copied and 
when they are their interface counter has nothing to do with the 
original interface, in fact it is the exact opposite, after a copy you 
need to make sure that the counter has been reset, which leads to 
believe that I misunderstood something.



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.


That is not a delegated interface that is a contained interface.

A delegated interface goes something like this

  IValue = interface
  ['{72D8B44F-5834-425D-AB3A-45785E94E2E4}']
function AsString:string;
  end;

  IMyInterface = interface
   ['{5E04F587-E4A0-42A7-850C-74C882BB5958}']
   procedure DoSomething;
  end;

  //tmyvalue can inherit from tContainedobject
  //for simplification.
  TMyValue = class(TInterfacedObject, IValue)
function AsString:String;
  end;
  //IValue must be part of TMyObject not a simple property.
  TMyObject = class(TInterfacedObject, IMyInterface, IValue)
  private
property MyValue :TMyValue implements IValue;
  end;

Τhe problem of a contained interface has already been solved, see the 
TContainedObject. To sum it up a contained object reference counting 
mechanism increments and decrements the container's reference counter 
it does not have a life of its own.


Sorry the rest look like a rabbit hole based on the wrong assumptions 
to me, there might be some merit but I have no will to search for it.



___
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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-07 Thread stdreamer

On 05/10/2016 19:13 μμ, Tony Whyman wrote:

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.

I'm guessing that by "coerced" you mean "reference a contained interface".


2. When the interface is copied that reference count is again incremented.
Interface can not be copied only implement objects can be copied and 
when they are their interface counter has nothing to do with the 
original interface, in fact it is the exact opposite, after a copy you 
need to make sure that the counter has been reset, which leads to 
believe that I misunderstood something.



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.


That is not a delegated interface that is a contained interface.

A delegated interface goes something like this

  IValue = interface
  ['{72D8B44F-5834-425D-AB3A-45785E94E2E4}']
function AsString:string;
  end;

  IMyInterface = interface
   ['{5E04F587-E4A0-42A7-850C-74C882BB5958}']
   procedure DoSomething;
  end;

  //tmyvalue can inherit from tContainedobject
  //for simplification.
  TMyValue = class(TInterfacedObject, IValue)
function AsString:String;
  end;
  //IValue must be part of TMyObject not a simple property.
  TMyObject = class(TInterfacedObject, IMyInterface, IValue)
  private
property MyValue :TMyValue implements IValue;
  end;

Τhe problem of a contained interface has already been solved, see the 
TContainedObject. To sum it up a contained object reference counting 
mechanism increments and decrements the container's reference counter it 
does not have a life of its own.


Sorry the rest look like a rabbit hole based on the wrong assumptions to 
me, there might be some merit but I have no will to search for it.



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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Marcos Douglas
Hi Graeme,

On Thu, Oct 6, 2016 at 12:05 PM, Graeme Geldenhuys
 wrote:
> Hello Marcos,
>
> On 2016-10-06 at 11:41, Marcos Douglas wrote:
>
>> The COM and CORBA names, are both wrong.
>> When you say COM, everybody thinks on Windows... that sad.
>
>
> Yes, both names are horribly inaccurate. Unfortunately I don't see FPC
> developers rectifying that any time soon. :-/

+1
Unfortunately.

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


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Marcos Douglas
On Thu, Oct 6, 2016 at 11:57 AM, Graeme Geldenhuys
 wrote:
> Hello Marcos,
>
> On 2016-10-06 at 11:25, Marcos Douglas wrote:
>
>> you need to declarate
>> two variables to do one job.
>> I don't like that and I think shouldn't be necessary.
>
> Well, to be fair, that example is not representative of a real-world
> application. In a real-world app, I would not declare and release
> objects and interface references like than - in the same procedure.

Yes of course, I know.

You will do some like that:

constructor TFoo.Create;
begin
  FTheObject := TBar.Create; // implements ITheObject
end;

destructor TFoo.Destroy;
begin
  FTheObject.Free;
end;

procedure TFoo.Execute;
begin
  CallSomethingThatAcceptsAnInterface(FTheObject);
end;

Nothing wrong. But you needs to create TFoo and manage it.

Regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Graeme Geldenhuys
Hello Marcos,

On 2016-10-06 at 11:41, Marcos Douglas wrote:

> The COM and CORBA names, are both wrong.
> When you say COM, everybody thinks on Windows... that sad.


Yes, both names are horribly inaccurate. Unfortunately I don't see FPC
developers rectifying that any time soon. :-/


Regards,
  Graeme


-- 
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

My public PGP key:  http://tinyurl.com/graeme-pgp

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


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Graeme Geldenhuys
Hello Marcos,

On 2016-10-06 at 11:25, Marcos Douglas wrote:

> you need to declarate
> two variables to do one job.
> I don't like that and I think shouldn't be necessary.

Well, to be fair, that example is not representative of a real-world
application. In a real-world app, I would not declare and release
objects and interface references like than - in the same procedure.


Regards,
  - Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

My public PGP key:  http://tinyurl.com/graeme-pgp

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


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Marcos Douglas
On Thu, Oct 6, 2016 at 7:36 AM, Graeme Geldenhuys
 wrote:
> On 2016-10-06 02:49, Marcos Douglas wrote:
>> I understand you, but reference counting help us to write a better
>> code, more object-oriented.
>
> That's got nothing to do with reference counting functionality. I use
> object-oriented coding practices all the time, but I don't need
> reference counting for that.

OOP, for me, It is closer to functional programming.
You should to code more declarative and less imperative.
Declare a variable; Create; try-finally; using line-by-line; call
Free... that is imperative, Procedural and not about OOP.

>> I'm using decorator pattern. No problem with it, but delegates makes
>> me write less code and the design is awesome.
>
> So, nothing stops you from using interface delegates with CORBA style
> interfaces. See the example code I just posted, where I converted the
> original example to use CORBA style interfaces instead.

I saw. But I can't use like that, as I explained above. Sorry... but thanks.

> I'm a huge believer and user of design patterns, and most of them I've
> implemented using Interfaces. Nothing there tells me I must use COM
> style interfaces.

The COM and CORBA names, are both wrong.
When you say COM, everybody thinks on Windows... that sad.

IMHO, interfaces with reference-counting is useful to write better
code, less imperative and using a design more closer to functional.

Best regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Marcos Douglas
On Thu, Oct 6, 2016 at 7:30 AM, Graeme Geldenhuys
 wrote:
> On 2016-10-05 16:26, Marcos Douglas wrote:
>> So, I coded a new example — more simpler, I think — to demonstrate the same
>> problem and prove that there is some wrong that is causing a memleak.
>
> And here is that example converted to use CORBA style interfaces and no
> memory leaks.

I've used CORBA before... but see your example, you need to declarate
two variables to do one job.
I don't like that and I think shouldn't be necessary.

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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Marcos Douglas
On Thu, Oct 6, 2016 at 7:11 AM, Graeme Geldenhuys
 wrote:
> On 2016-10-06 02:34, Marcos Douglas wrote:
>> But, the result was the same, even using D7.
>> So, is this by design? Sad...
>
> Sad and nasty indeed. But it seems it is “by design” or done for “Delphi
> compatibility”.
>
> It would be interesting to know what Delphi developers think of this.
> You should post the new code example and message to a Delphi newsgroup
> or Google+ forum and see what they think of that. If it has been around
> since the D7 days (and maybe even earlier), they might have an
> explanation or work-around for you.

That's a good idea. I'll do it.

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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Tony Whyman

On 06/10/16 11:08, Graeme Geldenhuys wrote:

I've seem some
COM Interface code where they had to resort to using raw Pointer types
etc to try and avoid reference counting and causing unexpected memory
leaks.
I have also seen plenty of examples of poor coding with classes, but the 
fact that someone writes bad object oriented programs doesn't mean that 
object oriented is a poor programming technique. Likewise, poor 
programming using com interfaces doesn't invalidate the use of com 
interfaces.


When you work with interfaces, there are two issues to consider:

1. How easy is the interface to use
2. How do you write the underlying classes.

To me, the first rules out delegated interfaces and COM. Even advanced 
level programmers will get it wrong and you will never get an easy to 
use interface with this combination. It looks like a design error that 
came from Delphi and was copied by FPC. However, if you rule out this 
combination, COM does make for what seems to be a very intuitive easy to 
use interface, in the same way that AnsiStrings are easy to use.


On the other hand, implementing the classes that provide a com interface 
does require some skill and is not for everyone.

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


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Graeme Geldenhuys
On 2016-10-06 02:49, Marcos Douglas wrote:
> I understand you, but reference counting help us to write a better
> code, more object-oriented.

That's got nothing to do with reference counting functionality. I use
object-oriented coding practices all the time, but I don't need
reference counting for that.


> I'm using decorator pattern. No problem with it, but delegates makes
> me write less code and the design is awesome.

So, nothing stops you from using interface delegates with CORBA style
interfaces. See the example code I just posted, where I converted the
original example to use CORBA style interfaces instead.

I'm a huge believer and user of design patterns, and most of them I've
implemented using Interfaces. Nothing there tells me I must use COM
style interfaces.


> For me, it's a bug. Sorry.

That I agree with. There seems to be a COM reference counted bug.


Regards,
  Graeme

-- 
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

My public PGP key:  http://tinyurl.com/graeme-pgp
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Graeme Geldenhuys
On 2016-10-05 16:26, Marcos Douglas wrote:
> So, I coded a new example — more simpler, I think — to demonstrate the same
> problem and prove that there is some wrong that is causing a memleak.

And here is that example converted to use CORBA style interfaces and no
memory leaks.


Program output:

==
[tmp]$ ./test.exe

IntegerValue:
TIntegerValue.Create
Number is 5
TIntegerValue.Destroy

MyApp:
TIntegerValue.Create
TMyApp.Create
Number is 10
TIntegerValue.Destroy
TMyApp.Destroy

MyAppAsInterface:
TIntegerValue.Create
TMyApp.Create
Number is 20
TIntegerValue.Destroy
TMyApp.Destroy

Heap dump by heaptrc unit
29 memory blocks allocated : 2045/2080
29 memory blocks freed : 2045/2080
0 unfreed memory blocks : 0
True heap size : 1409024 (32 used in System startup)
True free heap : 1408992

==


Regards,
  Graeme

-- 
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

My public PGP key:  http://tinyurl.com/graeme-pgp
program Project1;

{$mode objfpc}{$H+}
{$interfaces corba}

uses
  Classes,
  SysUtils;

type
  IValue = interface
  ['{C3151460-CA9B-447A-A7E8-86399222E844}']
function AsString: string;
  end;

  TIntegerValue = class(TObject, IValue)
  private
FValue: Integer;
  public
constructor Create(Value: Integer);
destructor Destroy; override;
function AsString: string;
  end;

  TMyApp = class(TObject, IValue)
  private
FValue: TIntegerValue;
function GetValue: IValue;
// this interface property doesn't need to be public
property Value: IValue read GetValue implements IValue;
  public
constructor Create(AValue: Integer);
destructor Destroy; override;
  end;

{ TIntegerValue }

constructor TIntegerValue.Create(Value: Integer);
begin
  inherited Create;
  FValue := Value;
  WriteLn('TIntegerValue.Create');
end;

destructor TIntegerValue.Destroy;
begin
  WriteLn('TIntegerValue.Destroy');
  inherited Destroy;
end;

function TIntegerValue.AsString: string;
begin
  Result := 'Number is ' + IntToStr(FValue);
end;

{ TMyApp }

function TMyApp.GetValue: IValue;
begin
  Result := FValue;
end;

constructor TMyApp.Create(AValue: Integer);
begin
  inherited Create;
  FValue := TIntegerValue.Create(AValue);
  WriteLn('TMyApp.Create');
end;

destructor TMyApp.Destroy;
begin
  FValue.Free;
  WriteLn('TMyApp.Destroy');
  inherited Destroy;
end;

// Program

procedure ExecuteIntegerValue;
var
  i: TIntegerValue;
  V: IValue;
begin
  WriteLn;
  WriteLn('IntegerValue:');
  i := TIntegerValue.Create(5);
  V := i;
  WriteLn(V.AsString);
  i.Free;
end;

procedure ExecuteMyApp;
var
  App: TMyApp;
begin
  WriteLn;
  WriteLn('MyApp:');
  App := TMyApp.Create(10);
  try
WriteLn(App.Value.AsString);
  finally
App.Free;
  end;
end;

procedure ExecuteMyAppAsInterface;
var
  app: TMyApp;
  V: IValue;
begin
  WriteLn;
  WriteLn('MyAppAsInterface:');
  try
app := TMyApp.Create(20);
V := app;
WriteLn(V.AsString);
  finally
app.Free;
  end;
end;

begin
  ExecuteIntegerValue;
  ExecuteMyApp;
  ExecuteMyAppAsInterface;
  ReadLn;
end.

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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Graeme Geldenhuys
On 2016-10-06 02:34, Marcos Douglas wrote:
> But, the result was the same, even using D7.
> So, is this by design? Sad...

Sad and nasty indeed. But it seems it is “by design” or done for “Delphi
compatibility”.

It would be interesting to know what Delphi developers think of this.
You should post the new code example and message to a Delphi newsgroup
or Google+ forum and see what they think of that. If it has been around
since the D7 days (and maybe even earlier), they might have an
explanation or work-around for you.

Regards,
  Graeme

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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Graeme Geldenhuys
On 2016-10-05 23:16, Tony Whyman wrote:
> Used properly reference counted interfaces are very powerful and allow 
> for some very elegant programming. Do you complain about AnsiStrings?

I have very powerful and elegant programming with CORBA interfaces too.
;-) Also as Martin mentioned, reference counting works wonders in simple
cases, but gets very nasty in medium to complex cases. I've seem some
COM Interface code where they had to resort to using raw Pointer types
etc to try and avoid reference counting and causing unexpected memory
leaks.  No such problems with CORBA Interfaces.

ps:
  You can obviously implement your own reference counted CORBA interface
  for the simple cases too. So you have the best of both worlds I guess,
  but when using CORBA Interfaces, I would avoid mixing reference
  counted and non-reference counted interfaces.

Regards,
  Graeme

-- 
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

My public PGP key:  http://tinyurl.com/graeme-pgp
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-06 Thread Graeme Geldenhuys
On 2016-10-06 05:54, Martin Schreiber wrote:
> Recently I had to revive my stone old AMD-K6 PC with Windows 95. What marvel, 
> that relict with its age-old applications provides a better user experience, 
> is snappier, more convenient and more productive than my newest Linux machine 
> with the modern desktops and applications.

We seem to have a lot in common. I still prefer Win2000 for any Windows
development (if I must use Windows). Memory efficient and very snappy
indeed! For Linux (actually FreeBSD) I long ago gave up on the extremely
bloated 'desktop environments' and have for years been using JWM (Joe's
Window Manager) - old school to the point, extremely fast and memory
efficient (8MB max) window manager. JWM stays out of my way, has hardly
any keyboard shortcuts to interfere with my daily programs, gives me a
task bar, virtual desktops and a popup menu. I don't need more than that.

Oh, and I run this on a Intel i7 3.5Ghz CPU with 32GB RAM. I prefer to
use my RAM for actual applications, VMs or the ZFS file system - not the
desktop environment. ;-)

Regards,
  Graeme

-- 
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

My public PGP key:  http://tinyurl.com/graeme-pgp
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Martin Schreiber
On Thursday 06 October 2016 00:16:22 Tony Whyman wrote:
> On 05/10/16 23:03, Graeme Geldenhuys wrote:
> > Martin Schreiber recently mentioned in another Interface discussion that
> > there is a very good reason he doesn’t use COM style interfaces…
> > Reference Counting!
>
> Used properly reference counted interfaces are very powerful and allow
> for some very elegant programming. Do you complain about AnsiStrings?
> They are reference counted. Would you really want to have to free every
> string explicitly? Dynamic arrays are similarly reference counted.
>
Reference counting is great for simple types like strings and dynamic arrays 
but is a nightmare with the venturesome mixture of COM-interface and classes 
from Delphi. Even reference counting for complex classes is no good idea IMO, 
I fear the times when FPC will implement ARC.
I don't think that a programming language should hide more and more of the 
internal working of the code he writes from the programmer. Take a look at 
the modern C++ programs; the LLVM-compiler is a good example. It is horrific 
slow. Stepping through the code shows that there are complex multi-level 
dynamic type conversion and dataaccess routines at almost every statement. 
The typical C++ programmer does not need to care about because the 
programming language takes care for the boring tasks. The typical C++ 
programmer actually *does* not care about performance because competing 
programs are not faster; they are written in a modern programming language 
too...
Recently I had to revive my stone old AMD-K6 PC with Windows 95. What marvel, 
that relict with its age-old applications provides a better user experience, 
is snappier, more convenient and more productive than my newest Linux machine 
with the modern desktops and applications.

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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Marcos Douglas
On Wed, Oct 5, 2016 at 7:16 PM, Tony Whyman
 wrote:
>
> Reference counted interfaces allow you to create classes (and objects) that
> behave in the same way as AnsiStrings. IMHO, a lot of standard packages
> would be greatly improved if they used com interfaces.

I agree with you 100%.

Best regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Marcos Douglas
On Wed, Oct 5, 2016 at 7:07 PM, Tony Whyman
 wrote:
>
>[...]
>
> 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.

That is it, counter-intuitive and  easy to get wrong.

Another thing easily to forget and get memleaks is not get the result
of constructors.
For example. Consider this:

function TFoo.Execute(const Name: string): string;
begin
  Result := TAction.Create(TTask.Create(Name)).Execute.ToString;
end;

- TTask is a class that takes a string in the constructor;
- TTask implements ITask, an interface;
- TAction is a class that receives an ITask interface in the constructor;
- TAction implements IAction, an interface;
- TAction has an Execute method that returns an IResult, an interface;
- IResult has a ToString method that returns the result in string format;

How many memory leaks we have here? 0, 1 or 2?
The answer is 1.

So, we need to declare an variable:

function TFoo.Execute(const Name: string): string;
var
  A: IAction;
begin
  A := TAction.Create(TTask.Create(Name));
  Result := A.Execute.ToString;
end;

Verbose and unnecessary, in my opinion.
Sometimes I forget to declare a variable, sometimes not... this is unproductive!

So, I created my own "design pattern" that I called: New Method.

The refactored code is:

function TFoo.Execute(const Name: string): string;
begin
  Result := TAction.New(TTask.New(Name)).Execute.ToString;
end;

I explained here
http://objectpascalprogramming.com/posts/interfaces-e-o-metodo-estatico-new/
but you need to translate.

>> 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?)

+1

>> 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.

I agree.

Best regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Marcos Douglas
On Wed, Oct 5, 2016 at 7:03 PM, Graeme Geldenhuys
 wrote:
> Martin Schreiber recently mentioned in another Interface discussion that
> there is a very good reason he doesn’t use COM style interfaces…
> Reference Counting!

I understand you, but reference counting help us to write a better
code, more object-oriented.

> Stick with CORBA style interfaces and things work much simpler. I have
> to agree. I’ve used CORBA style interfaces for years with great success
> and no memory leaks. You get all the benefits of Interfaces, but without
> the Reference Counting troubles and complexities. If you really are
> writing COM (Windows specific) applications, then fine — otherwise use
> CORBA style interfaces.

Simplicity. I think that's depends on point of view.
Today I write a better code than 3~4 years ago. For me it's much more simpler:
- no more .Free
- no more try-finally (to use .Free)
- no inheritance
- less variables and types declarations
- more functional design

I'm using decorator pattern. No problem with it, but delegates makes
me write less code and the design is awesome. None language has the
same feature, as far as I know. We have it, but doesn't work... well,
doesn't work in all cases, in all possibilities.

For me, it's a bug. Sorry.

Best regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Marcos Douglas
On Wed, Oct 5, 2016 at 6:51 PM, Graeme Geldenhuys
 wrote:
> On 2016-10-05 16:26, Marcos Douglas wrote:
>> Here is the output on my machine (Lazarus 1.7 r52880M FPC 3.0.1
>> i386-win32-win32/win64)
>
> Just so you know... bug or not, it seems to have the same behaviour as
> with Delphi 7. Compiled with D7 it has the exact same output. In fact,
> compiled with Delphi 7, the app doesn't quit at all. I had to Ctrl+C it.
> [...]
> Ignore that bit... Looking at the code in detail I see there was a
> ReadLn statement at the end. Dope! :)

But, the result was the same, even using D7.
So, is this by design? Sad...

Regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Tony Whyman

On 05/10/16 23:03, Graeme Geldenhuys wrote:

Martin Schreiber recently mentioned in another Interface discussion that
there is a very good reason he doesn’t use COM style interfaces…
Reference Counting!
Used properly reference counted interfaces are very powerful and allow 
for some very elegant programming. Do you complain about AnsiStrings? 
They are reference counted. Would you really want to have to free every 
string explicitly? Dynamic arrays are similarly reference counted.


Reference counted interfaces allow you to create classes (and objects) 
that behave in the same way as AnsiStrings. IMHO, a lot of standard 
packages would be greatly improved if they used com interfaces.

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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Tony Whyman


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

Hi Tony,

On Wed, Oct 5, 2016 at 1:13 PM, Tony Whyman
 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
 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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Graeme Geldenhuys
On 2016-10-05 16:26, Marcos Douglas wrote:
> So, I coded a new example — more simpler, I think — to demonstrate the same
> problem and prove that there is some wrong that is causing a memleak.

Martin Schreiber recently mentioned in another Interface discussion that
there is a very good reason he doesn’t use COM style interfaces…
Reference Counting!

Stick with CORBA style interfaces and things work much simpler. I have
to agree. I’ve used CORBA style interfaces for years with great success
and no memory leaks. You get all the benefits of Interfaces, but without
the Reference Counting troubles and complexities. If you really are
writing COM (Windows specific) applications, then fine — otherwise use
CORBA style interfaces.

Just my 2¢ worth.

Regards,
  Graeme

-- 
fpGUI Toolkit — a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

My public PGP key:  http://tinyurl.com/graeme-pgp
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Graeme Geldenhuys
On 2016-10-05 22:51, Graeme Geldenhuys wrote:
> In fact,
> compiled with Delphi 7, the app doesn't quit at all. I had to Ctrl+C it.


Ignore that bit... Looking at the code in detail I see there was a
ReadLn statement at the end. Dope! :)


Regards,
  Graeme

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


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Graeme Geldenhuys
On 2016-10-05 16:26, Marcos Douglas wrote:
> Here is the output on my machine (Lazarus 1.7 r52880M FPC 3.0.1
> i386-win32-win32/win64)

Just so you know... bug or not, it seems to have the same behaviour as
with Delphi 7. Compiled with D7 it has the exact same output. In fact,
compiled with Delphi 7, the app doesn't quit at all. I had to Ctrl+C it.



c:\Programming\test\interface_delegation_delphi>project1.exe

IntegerValue:
TIntegerValue.Create
Number is 5
TIntegerValue.Destroy

MyApp:
TIntegerValue.Create
TMyApp.Create
Number is 10
TMyApp.Destroy
TIntegerValue.Destroy

MyAppAsInterface:
TIntegerValue.Create
TMyApp.Create
Number is 20
^C
c:\Programming\test\interface_delegation_delphi>



Regards,
  Graeme

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


Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Marcos Douglas
Hi Tony,

On Wed, Oct 5, 2016 at 1:13 PM, Tony Whyman
 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.

> 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.

> 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?

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.

What do you think?

Best regards,
Marcos Douglas

On Wed, Oct 5, 2016 at 1:13 PM, Tony Whyman
 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

Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Tony Whyman

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] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

2016-10-05 Thread Marcos Douglas
Hi,

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.

So, I coded a new example — more simpler, I think — to demonstrate the same
problem and prove that there is some wrong that is causing a memleak.

=== BEGIN CODE ===

program Project1;

{$mode objfpc}{$H+}

uses
  Classes, SysUtils;

type
  IValue = interface
function AsString: string;
  end;

  TIntegerValue = class(TInterfacedObject, IValue)
  private
FValue: Integer;
  public
constructor Create(Value: Integer);
destructor Destroy; override;
function AsString: string;
  end;

  TMyApp = class(TInterfacedObject, IValue)
  private
FValue: IValue;
  public
constructor Create(Value: Integer);
destructor Destroy; override;
property Value: IValue read FValue implements IValue;
  end;

{ TIntegerValue }

constructor TIntegerValue.Create(Value: Integer);
begin
  inherited Create;
  FValue := Value;
  WriteLn('TIntegerValue.Create');
end;

destructor TIntegerValue.Destroy;
begin
  WriteLn('TIntegerValue.Destroy');
  inherited Destroy;
end;

function TIntegerValue.AsString: string;
begin
  Result := 'Number is ' + IntToStr(FValue);
end;

{ TMyApp }

constructor TMyApp.Create(Value: Integer);
begin
  inherited Create;
  FValue := TIntegerValue.Create(Value);
  WriteLn('TMyApp.Create');
end;

destructor TMyApp.Destroy;
begin
  WriteLn('TMyApp.Destroy');
  inherited Destroy;
end;

// Program

procedure ExecuteIntegerValue;
var
  V: IValue;
begin
  WriteLn;
  WriteLn('IntegerValue:');
  V := TIntegerValue.Create(5);
  WriteLn(V.AsString);
end;

procedure ExecuteMyApp;
var
  App: TMyApp;
begin
  WriteLn;
  WriteLn('MyApp:');
  App := TMyApp.Create(10);
  try
WriteLn(App.Value.AsString);
  finally
App.Free;
  end;
end;

procedure ExecuteMyAppAsInterface;
var
  V: IValue;
begin
  WriteLn;
  WriteLn('MyAppAsInterface:');
  V := TMyApp.Create(20);
  WriteLn(V.AsString);
end;

begin
  ExecuteIntegerValue;
  ExecuteMyApp;
  ExecuteMyAppAsInterface;
  ReadLn;
end.

=== END CODE ===


Here is the output on my machine (Lazarus 1.7 r52880M FPC 3.0.1
i386-win32-win32/win64)


=== BEGIN OUTPUT ===

W:\temp>project1.exe

IntegerValue:
TIntegerValue.Create
Number is 5
TIntegerValue.Destroy

MyApp:
TIntegerValue.Create
TMyApp.Create
Number is 10
TMyApp.Destroy
TIntegerValue.Destroy

MyAppAsInterface:
TIntegerValue.Create
TMyApp.Create
Number is 20

Heap dump by heaptrc unit
83 memory blocks allocated : 2017/2200
81 memory blocks freed : 1981/2160
2 unfreed memory blocks : 36
True heap size : 229376 (80 used in System startup)
True free heap : 229104
Should be : 229128
Call trace for block $01812928 size 20
  $004017DA  TMYAPP__CREATE,  line 59 of W:/temp/project1.lpr
  $00401B82  EXECUTEMYAPPASINTERFACE,  line 101 of W:/temp/project1.lpr
  $00401C08  main,  line 108 of W:/temp/project1.lpr
Call trace for block $018128C8 size 16
  $00401B82  EXECUTEMYAPPASINTERFACE,  line 101 of W:/temp/project1.lpr
  $00401C08  main,  line 108 of W:/temp/project1.lpr

W:\temp>

=== END OUTPUT ===


As you can see, the problem occurs just in the last test, when the classe
TMyApp is used as an instance of the interface IValue.

I don't know if this problem was solved on trunk. I would like to know.
If not solved, I will open an issue.

Best regards,
Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal