Introduction.

What is reference couting?

Reference counting is a technique that is used when you need to maintain several references to a same place, or more concretely to the same object without having to have several copies of this object in memory.

The derived problem of making reference to an object from several places appears when you no longer need the object, that is, determining the moment the memory of the object should be released. This doesn’t constitute a problem in languages with a good garbage collector (such as C#) but can suppose an enormous source of memory leaks in other projects. For example, suppose that have something like this (the code is in C++ but it is almost equal in Delphi)

class CReceipt {

   public:
     CClient *client;    // Pointer to an object containing some data
     // Here'd came the methods for the class ...

} class CInvoice {

   public:
     CClient *client;
     // More methods

}

and shomewhere in our code we have something like


  //..........   invoice = new CInvoice();   //... Rellenamos datos de la factura...   receipt = new CReceipt();   invoice->client = MyClient;   receipt->client = MyClient;   

Imagine we have two instances, one of the class invoices and the other of the class receipt and both are assigned to a certain client. They both keep a pointer to the assigned client. The problem arises when we must free the objects, when should we release the memory of the instance of the client?. If we release it in the destructor of the CInvoce class we can leave instances of CReceipt pointing to directions of invalid memory and if we do it in the destructor of CReceipt the opposite happens. If we do it in both, when we try to free the memory we’ll get an exception for the destructor that has executed last (since this memory has already been released).

Implementing reference counting

Although I would like to say: “there is a transparent, problem free solution to this” the truth is that there isn’t or at least I don’t know about it (although if I discover it I promise I’ll update this article). The ideal solution would be what Delphi makes automatically with interfaces.

Whenever you create an interface in Delphi (and in fact in almost any programming languages supporting interfaces) you must always inherit from the IUnknown interface which defines three methods: QueryInterface, AddRef and Release. I am not going to enter on details on each one of them but the important thing to keep in mind is that Delphi calls automatically AddRef and Release for the interfaces so that there is a single object in memory no matter how many references are made to the object through the interface.

procedure Example(InterfaceBasedObject : TMiObj); var MyInterface : IMySimpleInterface; begin

  // When we cast the object to the interface Delphi calls the AddRef method
  // which increases the number of references to the object
  MyInterface = InterfaceBasedObject As IMySimpleInterface; 

end; // When the execution reach this point and the interface variable gets out of

     // context Delphi automatically calls the Release method which will decrease the
     // reference count for the interface, if that reference count reaches zero, then
     // the object will be automatically freed

Unfortunately I haven’t found a way to achieve the same effect automatically, that is, make the reference count increase as we reference an object and decrease as we dereference it.

In order to simulate this behavior we can try to give a small roundup. What I’m really interested in is to have, somehow, a copy of the shared object, but keeping track of the reference made to it so that we can free it when we no longer need it. The simple way to do that is to have the object itself keep track of the references to him throughout the program, and when there are no references left, free it. This way each class that uses a reference to our object will be able to “release” it but only when the last reference has been consumed will the object really be freed.

type MyObject= class

  private
     // The reference count for the object
     m_refCount : integer;
  public
     constructor Create;
     procedure Free;

     function Copy : MiObjeto;

end;

{ MyObject } constructor MyObject.Create; begin

  m_refCount := 1;  // Set the reference count to one                     

end;

function MiObjeto.Copy : MiObjeto; begin

 // When we "copy" the object we increment the
 // reference count
 InterlockedIncrement(m_refCount);
 result := Self;

end;

procedure Free; begin

 // Decrement the reference count
 InterlockedDecrement(m_refCount);
 // If the reference count reach zero then
 // we release the object
 if m_refCount = 0 then
   Destroy;

end;

Once this have been defined we can copy the object by:

procedure TExample.MyMethod(invoice : TInvoice); begin

 // Get a copy of the client
 m_myReference := invoice.client.Copy;

end;

destructor Destroy; begin

 // Free the object as we always do
 if Assigned(m_myReference)
    m_myReference.Free;

end;