Channels ▼
RSS

Embedded Systems

Reference Counting and Object Harvesting in Delphi


Many of you will remember Delphi as revolutionizing Windows development when it was first released. Not only did Delphi deliver a complete application framework as a component library with visual design, but it did so with a true native language. This best of both worlds approach has kept Delphi a popular development solution on Windows.

With the most recent release of RAD Studio XE4, Delphi has become a multi-device and mobile solution that works for the first time on a non-Intel based processor, ARM. Delivering Delphi for iOS required changes to the language, compiler, runtime library, framework, and IDE. Perhaps the most important of these changes was the addition of automatic memory and object reclamation using reference counting.

Reclaiming Memory with ARC

From a language perspective, one of the new features we knew was going to be important on mobile was Automatic Reference Counting (ARC). ARC is a way to manage an object's lifetime without having to explicitly free/destroy the object. Basically, when the object goes out of scope, it is destroyed automatically (that is, when its reference count is 0). This is different from traditional garbage collection (GC) in that ARC is deterministic and objects are destroyed within the application flow rather than depending on a separate background task. ARC is important because it simplifies memory management considerably, which is critical on a mobile device with a low, fixed RAM profile. In fact, ARC is fully supported by Apple in the Objective-C language for iOS and is the preferred approach (as opposed to a GC) on Mac OS X as well.

As exciting and useful as enabling ARC for Delphi is, we also had to consider the huge amount of code that app developers would want to bring to mobile. In particular, a design goal of ours was to enable existing memory-management conventions and patterns to be ARC-compatible. Before ARC, Delphi developers used a specific coding pattern, based on the call to the Free method and generally protected by a try-finally exception-handling block. Given most Delphi code will be based on this pattern, it is important to understand what happens with Free, even under ARC. In short, existing code will work.

For example, a typical Delphi application would have code like:

class procedure TMySimpleClass.TryFinally;
var
  MyObj: TMySimpleClass;
begin
  MyObj := TMySimpleClass.Create;
  try
    MyObj.DoSomething;
  finally
    MyObj.Free;
  end;
end;

In the classic Delphi compiler, Free is a method of TObject, which checks whether the current reference is not nil and, if it is, calls the Destroy destructor, which removes the objects from memory after executing the proper destructor code.

In the new compiler, the call to Free is replaced with the assignment of the variable to nil. In the case where this was the last reference to the object, the object is removed from memory after calling its destructor. If there are other standing references when Free is called, only the reference count is decremented.

Similarly, a call such as:

FreeAndNil (MyObj);

sets the object to nil, and again triggers the object destruction only if there are no other variables referring to it. In most cases, this is correct, as you don't want to destroy objects used in another part of a program. There are scenarios, however, when you really want to execute the destructor code, such as closing a file handle or a database connection right away, regardless of the fact that there might be other pending references.

In other words, while they are often useless, calls to Free or FreeAndNil are generally completely harmless, and they can be kept in existing Delphi programs for the mobile platform. There are some limited scenarios, though, in which a different approach should be considered.

Forcing Object Harvesting

To allow the developer to force the execution of the destructor (without releasing the actual object from memory), the new compiler introduces a "dispose" pattern. If you call:

MyObject.DisposeOf;

there is a forced execution of the destructor code, even if there are pending references. At this point, the object is placed in a special state so that the destructor won't be called again in case of further disposal operations or when the reference counting reaches zero and memory is actually released.

This "disposed" state (or "zombie" state) is significant in that you can query an object for it via the Disposed property. This new method also is available on the classic compiler, but in this case, a call to DisposeOf is remapped to a call to the Free method. In other words, the new method makes no difference, but has been introduced to improve source code compatibility among different platforms.

Why is this dispose pattern required? Consider the case of a collection of elements or components owned by another component. A common usage pattern is to "destroy" a particular item in the collection in order to both clean up the item itself and remove it from the collection. Another common scenario is to destroy the collection or component owner and dispose of all the owned elements or components. In this case, if there are still pending references to the owned objects, it will likely force their destruction, or at least the execution of their destructor code.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video