AutoPointer with JWSCL [Update]
25
May
Posted by: Christian Wimmer in: Downloads, JEDI Windows Security Code Lib
JWSCL provides access to auto pointers or objects. It means that allocated space or objects are automtically destroyed/freed as soon as the auto object runs out of scope. What is a scope? A scope exists as long as the (I say) parent object exists. Parent objects can be:
- The process. The auto pointer and thus the object exist as long as the process runs. The object will be destroyed when the process is destroyed.
- A class or record. The auto pointer exists as long as the class instance exists. If the instance is freed the managed auto pointer object will be freed as well.
What is not a parent object?
- begin end. In contrast to C++, a begin/end construct does not allow to create a variable scope. You have to create a new function do achieve the same effect.
- A pointer to an object. Auto pointer to any object (class, record, variable) will not be automatically destroyed. You have to free the memory manually (Dispose, FreeMem) to let the auto pointer take effect.
The current release only allows to create or wrap objects. It is done by the methods of TJwAutoPointer.
The following sample shows how to avoid to manually call free. It uses the Wrap method of TJwAutoPointer to activate the managed pointer mechanism. There is no method to undo this call.
-
procedure X;
-
var
-
ManagedObject : TJwSecurityID;
-
AutoPtr : IJwAutoPointer;
-
begin
-
ManagedObject := TJwSecurityID.Create(…);
-
AutoPtr := TJwAutoPointer.Wrap(ManagedObject);
-
…
-
//no need to free ManagedObject
-
end;
The advantage of the auto pointer approach is that we do not need to call Free for every possible exit. Even exceptions cannot avoid that the managed object is destroyed.
The next sample demonstrates this fact.
-
procedure X;
-
var
-
ManagedObject : TJwSecurityID;
-
AutoPtr : IJwAutoPointer;
-
begin
-
ManagedObject := TJwSecurityID.Create(…);
-
AutoPtr := TJwAutoPointer.Wrap(ManagedObject);
-
-
if DoExit then
-
exit;
-
-
if Error then
-
raise Exception.Create(…);
-
…
-
//no need to free ManagedObject
-
end;
The same way can be used to add the IJwAutoPointer variable into classes and records.
-
uses
-
SysUtils,
-
JwsclComUtils;
-
type
-
TMyClass = class
-
public
-
N : String;
-
x : IJwAutoPointer;
-
constructor Create(Name : String);
-
destructor Destroy; override;
-
end;
-
-
TMyRecord = record
-
x : IJwAutoPointer;
-
end;
-
-
constructor TMyClass.Create(Name: String);
-
begin
-
inherited Create;
-
Writeln(‘Create :’,Name);
-
N := Name;
-
end;
-
-
destructor TMyClass.Destroy;
-
begin
-
Writeln(‘DesTMyRecordoy: ‘,N);
-
inherited;
-
end;
-
-
procedure X;
-
var Y,Z : TMyClass;
-
begin
-
Y := TMyClass.Create(‘1′);
-
Z := TMyClass.Create(‘2′);
-
Y.x := TJwAutoPointer.Wrap(Z);
-
-
Y.Free;
-
end;
-
-
procedure Y(UseDispose : Boolean);
-
var
-
L : TMyRecord;
-
pL : ^TMyRecord;
-
Y : TMyClass;
-
begin
-
new(pL);
-
Y := TMyClass.Create(‘1′);
-
PL.x := TJwAutoPointer.Wrap(Y);
-
-
writeln;
-
if UseDispose then
-
dispose(PL);
-
end;
A call to X returns:
Create :1
Create :2
Destroy: 1
Destroy: 2
As you can see, the managed object (Name : “2″) is shortly destroyed after the parent object is destroyed. You should know about this fact, because accessing the parent object will fail (if you are luck) in an exception.
A call to Y(false) returns
Create :1
A call to Y(true) returns
Create :1
Destroy: 1
The next release of JWSCL will bring support for pointers created by New and GetMem as well as LocalAlloc. It will also implement thread safe locking mechanisms.
[Update]
There is no need to save the COM object if you want to keep the object only alive in a single function.
Just wrap it.
-
procedure X;
-
var Y,Z : TMyClass;
-
begin
-
Y := TMyClass.Create(‘1′);
-
TJwAutoPointer.Wrap(Y);
-
end;
You even can wrap it several times. All wrapped up instances will be freed, regardeless of the variable’s name.
-
procedure X;
-
var Y,Z : TMyClass;
-
begin
-
Y := TMyClass.Create(‘1′);
-
TJwAutoPointer.Wrap(Y);
-
-
Y := TMyClass.Create(‘2′);
-
TJwAutoPointer.Wrap(Y);
-
end;
Of course you can’t access the first object anymore. But sometimes it comes quite handy.
convert this post to pdf.
4 Responses
Zzz
22|Apr|2008 1class function TJwAutoPointer.CreateInstance(
const ClassReference : TComponentClass;
const Owner : TComponent): IJwAutoPointer;
begin
Result := Wrap(classReference.Create(nil));
end;
nil should be owner?
Christian Wimmer
22|Apr|2008 2Yes indeed. Fixed in repository.
Joe White
27|Apr|2008 3“The advantage of the auto pointer approach is that we do not need to call Free for every possible exit. Even exceptions cannot avoid that the managed object is destroyed.”
Of course, try..finally gets you the same thing, even in the case of Exit. But your technique could still come in handy sometimes, as long as you don’t care what order things are freed.
Oliver
28|Apr|2008 4Joe, you’re totally right, but you miss the beauty of the approach of aut-pointers.
They are a long known concept in C++ and there are alternative uses which use the same concept (although hard to map to Delphi). One very visual example is the hourglass cursor if some operations is underway. Now in Delphi you would write something like:
In C++ you could then instantiate a simple wrapper class which takes care of the “reset-operation” in its destructor. So this becomes a one-liner
Same for auto-pointers: they tend to make the code more readable and consequently more maintainable.
// Oliver
Leave a reply
Search
Paypal donation (EUR)
Categories
Most Viewed
Archives
Tags
ACL callback COM Conversion CreateProcess DACL Delphi dialog DidYouKnow DLL documentation Download elevation factory file Handle header HowTo interface JWA JWSCL Kernel Microsoft KillProcess Laptop mail mailinglist manifest permission Privilege Process ProcessExplorer RunEl Russinovich Service Setup Sid TerminateProcess Theme Thread Token UAC user Vista Window WindowsRecent Posts
Recent Comments
Blogroll
Pages
Meta