Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
495 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi



Loremo - the 1.5 liter car coming in 2009




Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (8)


Garbage Collector for Delphi ApplicationsGo to Frederico Pissarra's websiteFormat this article printer-friendly!Bookmark function is only available for registered users!
Product:
Delphi 5.x (or higher)
Category:
Object Pascal
Skill Level:
Scoring:
Last Update:
12/05/2001
Search Keys:
delphi delphi3000 article borland vcl code-snippet garbage collector garbage-collector SafeGuard
Times Scored:
8
Visits:
5948
Uploader: Frederico Pissarra
Company: Tech Overseas do Brasil Ltd.
Reference: Tech Overseas
 
Question/Problem/Abstract:
How to implement a garbage collector in Delphi?
Answer:



  One of the top characteristics of C++ is that destructors are
  called automatically.  In Object Pascal we must call destructors
  explicitlly.

  Objects based on IUnknown interface, when loosing scope, calls
  _Release() method automatically.  The TInterfacedObject class
  implements the _Release(), calling the class destructor (See
  $(DELPHI)\Source\RTL\SYS\System.pas).

  To implement a garbage colletor the only thing we have to do is to create
  an object that instantiates our TObject derived objects for us
  and, when the destructor is called, it destroys our object
  automatically. I.e, an proxy object.

-----------%<-----cut here--------%<----------------------------------------
unit GarbageCollector;

interface

type
  ISafeGuard = type IUnknown;

// Use the Guard function to instantiate the object!
function Guard(Obj : TObject; out SafeGuard : ISafeGuard) : TObject;

implementation

type
  TSafeGuard = class(TInterfacedObject, ISafeGuard)
  private
    FObj : TObject;
  public
    constructor Create(Obj : TObject);
    destructor Destroy; override;
  end;

constructor TSafeGuard.Create(Obj : TObject);
begin
  FObj := Obj;
end;

destructor TSafeGuard.Destroy;
begin
  if Assigned(FObj) then
  begin
    FObj.Free;
    FObj := nil;
  end;
  inherited Destroy;
end;

function Guard(Obj : TObject; out SafeGuard : ISafeGuard) : TObject;
begin
  Result := Obj;
  SafeGuard := TSafeGuard.Create(Obj);  // Create the proxy obj.
end;

end.
-----------%<-----cut here--------%<----------------------------------------


To create a new object derived from TObject, simply do this:

-----------%<-----cut here--------%<----------------------------------------
  var obj : TMyObj;
      SafeGuard : ISafeGuard;

  obj := TMyObj(Guard(TMyObj.Create, SafeGuard));
-----------%<-----cut here--------%<----------------------------------------


where TMyObj is a TObject decendant.

Here, an console application example:

-----------%<-----cut here--------%<----------------------------------------
{$APPTYPE CONSOLE}
program Test;

uses GarbageCollector;

{ --- Test class --- }
type
  TTest = class(TObject)
  public
    constructor Create;
    destructor Destroy; override;

    procedure Test;
  end;

{ ---- Test members --- }
constructor TTest.Create;
begin
  WriteLn('Create()');
end;

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

procedure TTest.Test;
begin
  WriteLn('Test()');
end;
{ ---- End Of Test members --- }

{ ---- Test Procedure --- }

procedure TestProc;
var SafeGuard : ISafeGuard;
    obj : TTest;
begin
  obj := TTest(Guard(obj.Create, SafeGuard)); // Create!
  obj.Test;
  { Notice that we are not explicitlly destroying the object here! }
end;
{ ---- End Of Test Procedure --- }


begin
  TestProc;
end.
-----------%<-----cut here--------%<----------------------------------------

This trick is documented on JCL (Project Jedi Component Library).
It is not my ideia, only a simplification.  The original code was
designed by Jeroen Speldekamp





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
This a crazy idea !!!!!!
    O R (May 15 2002 10:49AM)

First : we don't need a garbage collector in delphi.... or develop in java if you want :o)

Last : what you said about c++ and pascal is wrong.
This is 2 ways for doing the same thing (see the code in system.pas and all internal object procedure management for create, destroy and virtuality ;-)

In pascal you call "TheClass.Create" and "TheInstance.Free"
In c++ you call "new TheClass" and "delete TheInstance"
But in fact, same the thing is made.......

Respond

another way - use TComponent and free notifications
    Rossen Assenov (Dec 13 2001 8:08PM)

unit ComponentSafeUnit;

interface

type TInterfacedComponent = class (TComponent)
     private
      FRefCount : Integer;
     protected
      function _AddRef  : Integer; stdcall;
      function _Release : Integer; stdcall;
     public
      procedure BeforeDestruction; override;
     end;

     IComponentSafe = interface
      function Safe : TComponent;
     end;

     TComponentSafe = class (TInterfacedComponent, IComponentSafe)
      function Safe : TComponent;
     end;

function NewSafe : IComponentSafe;

implementation

function TInterfacedComponent._AddRef: Integer;
begin
  Result := InterlockedIncrement (FRefCount);
end;

function TInterfacedComponent._Release: Integer;
begin
  Result := InterlockedDecrement (FRefCount);

  if   Result = 0
  then Destroy;
end;

procedure TInterfacedComponent.BeforeDestruction;
begin
  if   FRefCount <> 0
  then raise Exception.Create  (ClassName + ' not freed correctly');
end;

function TComponentSafe.Safe : TComponent;
begin
  Result := Self;
end;

function NewSafe : IComponentSafe;
begin
  Result := TComponentSafe.Create (Nil);
end;

---------------------------------------------------------

usage :

procedure Test;
begin
  with NewSafe, TMyComponent.Create (Safe) do
  begin
    // do something with TMyComponent
    // you can even call MyComponent.Free  and it will notify the Safe
  end;
end;
Respond

Very interesting
    Ken Wilcox (Dec 13 2001 6:46AM)

I seemed to have read this information before... oh ya on the BORLAND COMUNITY SITE. http://community.borland.com/article/0,1410,27465,00.html.
Respond

RE: Very interesting
Frederico Pissarra (Dec 13 2001 12:31PM)

Thank you very much...

I got this tip from Project Jedi - I believe that Borland Community article was writen based on that too...

Respond

Coding practices
    Bill Artemik (Dec 12 2001 1:19PM)

If it helps a C++ programmer migrate to Delphi / Object Pascal then it works. Arguments about coding style can go on forever. It's like asking which color is better, Red or Blue?

With Kylix E2 on the scene now, Object Pascal is going to see MANY more C++ developers converting Gates apps into global apps (from Windows to multi-platforms like Linux and Unix).
Respond

Bad programming habbit?
    Tommy Andersen (Dec 6 2001 12:56PM)

Even if it looks great and all, I can't actually agree with you that this is good code...
If a programmer forget to destroy his/her's objects etc., then they deserve to get bad applications instead of creating workarounds for their lousy code...
I could write a lot of arguments for this but it should be pretty obvious what I mean! ;)


Best Regards
Tommy Andersen
EasyWare.org

Respond

RE: Bad programming habbit?
Frederico Pissarra (Dec 6 2001 1:51PM)

Thank you very much for your comments!

I donīt agree. There are some circunstances where garbage colletion is a very good thing. In fact, I donīt like the object creation and destruction style of Object Pascal. C++ is a lot simplier:

  obj = new TMyObj;

  delete obj;

The first, automatically calls the object constructor. The second, automatically calls the object destructor. Another example:

  void f(void)
  {
    TMyObj obj;

    /* do something here */
  }

The constructor is called when obj gains the scope... And the destructor is automatically called when f() finishes.

There are a lot of features of C++ not implemented in Object Pascal - ok, there are a lot of "crazy" features as well!

Take a look at the VCL source... Borland (Inprise) use interface a lot (and garbage collector!).
Respond

RE: RE: Bad programming habbit?
anonymus (Dec 6 2001 1:56PM)

Even if Borland uses it doesn't mean it's a good way of coding... ;)

I guess it's a little bit of how you like your code too. I prefer the pascal way of coding, and have never ever liked the C++ way! ;) It's too messy! hehe.


Tommy

Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
A. B. Talal
 
   














 







     
  Copyright Đ 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)