Solved

function returning TInterfacedObject

Posted on 2003-10-24
6
972 Views
Last Modified: 2011-09-20
It is convenient, in my code, for me to have a function returning an instance of an object without me having to worry about managing that instance .. in other words, I am looking for garbage collection.

I don't know much about interfaces, but I thought the following might work
type
Tfred=class(TinterfacedObject)
  private
  function getAsString: String;
public
  property AsString : String read getAsString;
end;


function Tfred.getAsString: String;
begin
result := inttostr(refCount);
end;

type
 Ttom = class
public
  function aFred: Tfred;
end; // Ttom

 function Ttom.aFred: Tfred;
 begin
  result :=Tfred.create;
  // never cleaned up
 end;


or even
function myFred:Tfred; begin result:=Tfred.create; end;


procedure TForm1.btnTestReferencecountingClick(Sender: TObject);
var k: integer; tom : TTom;

begin
tom := Ttom.create;
for k:=1 to 100 do begin
dsmemo1.out([tom.afred.AsString, myFred.AsString]);
end;
tom.free;
end;

Is this a correct usage of TinterfacedObject?

I don't think reference counting is going to come into it, but will all my instances of Tfred be released at the end of the calling procedure??

Also, I don't understand how the cleanup can happen correctly without Delphi maintaining some sort of internal list (in which case there would be a hidden overhead, compared to managing the lifetimes yourself). I understand the reference count is maintained with the object, but somehow - at run time - the app must tell the object that it is no longer in scope ..

enlightenment and code correction sought, please
0
Comment
Question by:Mutley2003
  • 4
6 Comments
 
LVL 9

Expert Comment

by:mocarts
ID: 9619156
Hi, Mutley :)
Your code will work, but you still need to free your objects, since reference counting is used only to interfaces.
TInterfaceObject is helper object which impelements AddRef, Release methods of IInterface. You should declare and implement your IFred interface to use reference counting..
here will be reworked code:

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  end;

  IFred = interface
    function AsString: string;
  end;

  TFred = class(TInterfacedObject, IFred)
  public
    destructor Destroy; override;
    function AsString: string;
  end;

  TTom = class
    function GetFred: IFred;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TFred }

function TFred.AsString: string;
begin
  Result := inttostr(RefCount);
end;

destructor TFred.Destroy;
begin
  ShowMessage('Destroing');
  inherited;
end;

// simple function to get Fred
function GetFred: IFred;
begin
  Result := TFred.Create;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Tom: TTom;
  i: integer;
begin
  tom := TTOm.Create;
  try
    for i := 0 to 10 do
     // scope of IFred is limited only to this line
     //(actually there is two separate TFred interface instances used)
      Memo1.Lines.Add(Tom.GetFred.AsString + '; '+ GetFred.AsString);
  finally
    tom.Free;
  end;
end;

{ TTom }

function TTom.GetFred: IFred;
begin
  Result := TFred.Create;
end;

wbr, mo.
0
 
LVL 6

Expert Comment

by:swift99
ID: 9622500
Delphi's reference counting is, in my experience, not useful.  If you add an interface object to a list, for example, the reference count is not updated, so your objects may disappear "randomly", or fail yto be garbage collected and the reason not be apparent.
0
 
LVL 6

Expert Comment

by:swift99
ID: 9622509
Even in Java, you have to pay careful attention to the GC and the memory model, or it works against you rather than for you.  Java uses a access graph rather than a reference count, which is mroereliable, and even it has problems.

In Delphi, it is far better to ensure that you free everything than to depend on the GC model.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 6

Accepted Solution

by:
swift99 earned 500 total points
ID: 9623912
Delphi does not manage a list.  Every call to the object through the TInterfacedObject code checks reference count.  If reference count is zero then it frees the object.

This leads to interesting effects if you create an object, add it to a list, and then attempt to perform some operations against it.  The first operation succeeds, but it also frees the object.  The second operation fails randomly because the object has been freed, and its memory (which you are still pointing at) is in an indeterminate state.

The overhead of this is huge.  In the same code, going through both the "interface" model and the pure inheritance model, the interface model was able to perform 5,000 operations per second.  The identical code, refactored to use the pure inheritance model, was able to perform 12,000,000 operations per second.

All tests were performed under Windows 98 on the same 800 MHz machine.  At the higher speed, a complete regression test takes roughly 11 hours, so you can see why I threw out the interface model once I did force it to work.
0
 

Author Comment

by:Mutley2003
ID: 9661515
swift99

ok, I am convinced. With only a little more work I can use the traditional approach, and with results like the ones you have obtained, I see no reason to venture into the uncharted waters of interfaces and garbage collection

thanks
0
 
LVL 6

Expert Comment

by:swift99
ID: 9662885
The implementation of the "interface" concept in Delphi was tied in to COM.  This was a deliberate decision because of the way that Windows architecture was going.  It is not fair to write off the interfaces approach entirely

Delphi Interfaces are still useful in two places:
1. any interaction through the COM or ActiveX API - say a DLL that implements a COM object for use by an outsode program
2. operations where performance is not an issue, and you can control the refernces yourself - for example the DUnit testing framework

In Java, the designers did not labour under the need to conform to a M$oft architecture direction of the week, so interfaces are implemented as a parallel VMT (array of pointers) and are very light weight.

Interfaces and garbage collection should be considered as two independent questions, even though they have been rolled together in the Delphi model.  I think that the Delphi architects recognize this flaw, but too much code has been written for this blurred paradigm for them to arbitrarily change it and break their customers' code base.
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…

679 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question