Using SafeGuards

By: Matthias Thoma

Abstract: This article describes SafeGuards -- an easy way of automatic resource destruction.

Using SafeGuards

This article describes SafeGuards -- an easy way of automatic resource destruction.

By Matthias Thoma

The Jedi Code Library's SafeGuards provide the functionality of automatic resource destruction. This feature is not as powerful as automatic garbage collection which some programming languages provide but it is very useful anyway.

Everyone knows code that creates an object, works with the object and frees it again in the same procedure. SafeGuards are especially appropriate in such situations.

An example of the create-work-free structure is illustrated in the following code:

var
  bmp: TBitmap;
  jpeg: TJPEGImage;

begin
  bmp := TBitmap.Create;
  jpeg := TJPEGImage.Create;
  try
    bmp.LoadFromFile('C:test.bmp');
    jpeg.Assign(bmp);
    jpeg.SaveToFile('C:test.jpg');
  finally
    bmp.free;
    jpeg.free;
end;

Using SafeGuards, the code looks like this:

var
  bmp: TBitmap;
  jpeg: TJPEGImage;
  is1, is2 : ISafeGuard;

begin
  bmp := TBitmap(Guard(TBitmap.Create,is1));
  jpeg := TJPEGImage(Guard(TJPEGImage.Create,is2));
  bmp.LoadFromFile('C:test.bmp');
  jpeg.Assign(bmp);
  jpeg.SaveToFile('C:test.jpg');
end;

Another common situation is memory allocation:

var
  p: pointer;

begin
  try
    GetMem(p,100000000);
    // Work with p
  finally
    FreeMem(p);
  end;
end;

Using SafeGuards:

var
  p: pointer;
  is1: ISageGuard;
  
begin
  GetMem(p,100000000);
  Guard(p,is1);
  // Work with p
end;

or even easier:

var
  p: pointer;
  is1: ISageGuard;
  
begin
  p := GuardAllocMem(100000000,is1);
  // Work with p
end;

If you need proof - here it is:

procedure Prove;
var
  p: pointer;
  h: THeapStatus; 

  procedure AllocPointer(SGOn: Boolean);
  var
    is1: ISafeGuard;
  
  begin
    GetMem(p, 100000);
     if SGON then
       Guard(p,is1);
  end; 

begin
  h := GetHeapStatus;
  ShowMessage(inttostr(h.TotalAllocated));
  AllocPointer(False); // Without SafeGuard
  h := GetHeapStatus;
  ShowMessage(inttostr(h.TotalAllocated));
  FreeMem(p, 100000); 
  h := GetHeapStatus;
  ShowMessage(inttostr(h.TotalAllocated));
  AllocPointer(True); // SafeGuard
  h := GetHeapStatus;
  ShowMessage(inttostr(h.TotalAllocated));
end; 
What is the secret? ISafeGuard is an interface. Delphi guarantees that an interface variable is released when it it leaves its scope. So the resource is associated with the interface and is released together with the interface.

The function Guard is declared as:

function Guard(Mem: Pointer;
         out SafeGuard: ISafeGuard): 
         pointer; overload;
function Guard(Obj: TObject; 
         out SafeGuard: ISafeGuard): 
         TObject; overload;

The results are copies of the input parameters Mem or Obj. This allows you to call Guard within functions. Other useful Guard-related functions are:

ISafeGuard.ReleaseItem  

Disassociates the Resource from the SafeGuard. The responsibility of releasing the object is given back to you.

ISafeGuard.GetItem

Returns a pointer to the resource associated with the SafeGuard.

ISafeGuard.FreeItem

Frees the Item associated with the SafeGuard.

To download the Jedi Code Library please visit www.delphi-jedi.org


Server Response from: BDN10A

 
© Copyright 2008 Embarcadero Technologies, Inc. All Rights Reserved. Contact Us   Site Map   Legal Notices   Privacy Policy   Report Software Piracy