[fpc-devel] Generics.Collections as package for Lazarus or package for FPC RTL

silvioprog silvioprog at gmail.com
Sat Jan 30 19:01:09 CET 2016


On Fri, Jan 29, 2016 at 1:24 PM, Marco van de Voort <marcov at stack.nl> wrote:

> In our previous episode, Sven Barth said:
> > > Interfaces are relatively slow. Not only because of the refcounting,
> but
> > > returning interfaces in a tight loop (e.g. to get the elements of an
> > > enumeration) would be a new allocation each time.
> >
> > Note: the enumerator of a for-in is only fetched once before the loop, so
> > it does not really matter whether it's an interface or record as long as
> > the elements themselves aren't on demand allocated interfaces.
>
> The trouble is that you then have to avoid for-in for many potentially
> small
> iterations as in the hash case.


Hm... that's my case. I have an object list that the key is an integer and
the value is an object, ie a hash map.

However, some years ago I got a problem using interfaces in an old draft
that I made, so to fix the problem I chose abstract class instead of
interface. I don't know if it is a compiler behaviour or something that I
forgot, the test is:

=== begin code ===

  ITest = interface
    ['{1DB8BD50-FCA2-40B3-B25B-A858DD206D26}']
    procedure SetTest(ATest: ITest);
  end;

  TTest1 = class(TInterfacedObject, ITest)
  private
    FTest: ITest;
  public
    procedure SetTest(ATest: ITest);
    property Test: ITest read FTest write FTest;
  end;

  TTest2 = class(TInterfacedObject, ITest)
  private
    FTest: ITest;
  public
    procedure SetTest(ATest: ITest);
    property Test: ITest read FTest write FTest;
  end;

...

procedure TTest1.SetTest(ATest: ITest);
begin
  FTest := ATest;
end;

procedure TTest2.SetTest(ATest: ITest);
begin
  FTest := ATest;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  VTest1, VTest2: ITest;
begin
  VTest1 := TTest1.Create;
  VTest2 := TTest1.Create;
  VTest1.SetTest(VTest2);
  VTest2.SetTest(VTest1);
end;

=== end code ===

It throws some memory leaks, so to fix the problem I used abstract class:

=== begin code ===

  TTest = class abstract
  public
    procedure SetTest(ATest: TTest); virtual; abstract;
  end;

  TTest1 = class(TTest)
  private
    FTest: TTest;
  public
    procedure SetTest(ATest: TTest); override;
    property Test: TTest read FTest write FTest;
  end;

  TTest2 = class(TTest)
  private
    FTest: TTest;
  public
    procedure SetTest(ATest: TTest); override;
    property Test: TTest read FTest write FTest;
  end;

...

procedure TTest1.SetTest(ATest: TTest);
begin
  FTest := ATest;
end;

procedure TTest2.SetTest(ATest: TTest);
begin
  FTest := ATest;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  VTest1, VTest2: TTest;
begin
  VTest1 := TTest1.Create;
  VTest2 := TTest1.Create;
  VTest1.SetTest(VTest2);
  VTest2.SetTest(VTest1);
  VTest1.Free;
  VTest2.Free;
end;

=== end code ===

However, I need to use the ARC feature in some occasions, and it seems that
the better FPC entity that already implements that is the
TInterfacedObject. :-/

--
Silvio Clécio
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20160130/8270d949/attachment.html>


More information about the fpc-devel mailing list