views:

751

answers:

4

I have a graph like structure. I don't know exactly when to destroy the objects in traditional Delphi manner, instead I would like to implement something like reference counted objects. I know that I can use something like object.GetReference and object.Release instead of Free, and use a private variable for reference counting, but is there any better way?

Thanks

+3  A: 

You can use interfaces instead of objects, underlaying objects will be automatically reference counted, and the best thing is that delphi will destroy objects for you, when refcount = 0.

Jk
+2  A: 

As you probably know, Delphi does not have a garbage collector.

You're best bet would be to have your objects descend from TInterfacedObject. Something like

type
  IMyObject = interface
    [Guid]
  end;

  MyObject = class(IMyObject, TInterfacedObject)
  end;

var
  myObject: IMyObject;
begin
  myObject := TMyObject.Create;
end

The myObject variable is reference counted and will be freed when its reference count drops to zero.

Lieven
+12  A: 

If you have problems determining the correct way (place, order and so on) of destroying standard objects in a Delphi program, then using reference counted objects or interfaces instead will not help you at all.

I understand that you want the nodes in a graph to keep references to each other, and when there are no references left to an object, it should be destroyed automatically. But consider the fact that two nodes can each have a reference to the other node, and the ref count will never reach 0 again, so that those objects will never be freed. You will need to break at least one of the references / dependencies manually. And if you have to do this anyway, then you can as well skip reference counting altogether. For some more information see the Wikipedia article about weak references. Interfaces can be used in Delphi for reference counting, but weak references can only be maintained with clever typecasting. For an example see this source code and its comments.

One idea that you might want to explore is to keep the standard lifetime management for your objects, and let the graph objects keep track of the dependencies instead.

Let each graph object have a list of other objects that it has connections with. Now you can simply free any of the objects, and the housekeeping code for the list will remove all references to the object being destroyed from all other objects. If you want to modify the graph you simply free the nodes that you want removed, and the dependencies will be updated. If you want to destroy the whole graph, just destroy all nodes. Basically you have a list of nodes (ownership, lifetime management) and another data structure for describing the graph.

mghie
A: 

If you are using D2009 you can use Barry Kelly's implementation of Smart Pointers.

http://barrkel.blogspot.com/2008/11/somewhat-more-efficient-smart-pointers.html

Otherwise using interfaces is your best bet. Create an interface with ALL the functionality you require, create an object that implements that interface and descends from TInterfacedObject and then use interfaces everywhere, not the object.

SeanX
Beware: using either smart pointers or interfaces everywhere in graph structures will create problems with cyclic references. These need to be broken up manually, or weak references need to be employed as well.
mghie