The ISafeGuard approach is not a smartpointer but creating a scope to some resource. There is a important difference: a smart pointer combines the resource and its lifetime management into one entity.
Also the record based approach is the most naive one - while Spring4D offers this one as well it has a more advanced one.
As for performance: measure it yourself:
program MeasureIt;
{$APPTYPE CONSOLE}
uses
Spring,
Diagnostics,
Classes,
SysUtils,
JclSysUtils;
const
ADD_COUNT = 10;
CREATE_COUNT = 100000;
procedure MeasureSpring;
var
s: IShared<TStringList>;
i: Integer;
begin
s := Shared.Make(TStringList.Create);
for i := 1 to ADD_COUNT do
s.Add(i.ToString);
end;
procedure MeasureJcl;
var
s: TStringList;
g: ISafeGuard;
i: Integer;
begin
s := TStringList.Create;
Guard(s, g);
for i := 1 to ADD_COUNT do
s.Add(i.ToString);
end;
procedure MeasureClassic;
var
s: TStringList;
i: Integer;
begin
s := TStringList.Create;
try
for i := 1 to ADD_COUNT do
s.Add(i.ToString);
finally
s.Free;
end;
end;
procedure Main;
var
sw: TStopwatch;
i: Integer;
begin
sw := TStopwatch.StartNew;
for i := 1 to CREATE_COUNT do
MeasureSpring;
Writeln(sw.ElapsedMilliseconds);
sw := TStopwatch.StartNew;
for i := 1 to CREATE_COUNT do
MeasureJcl;
Writeln(sw.ElapsedMilliseconds);
sw := TStopwatch.StartNew;
for i := 1 to CREATE_COUNT do
MeasureClassic;
Writeln(sw.ElapsedMilliseconds);
end;
begin
Main;
Readln;
end.
The implementation in Spring 1.2.2 (currently released version) uses very optimized code for the smart pointer itself avoiding the overhead of an object allocation and all the code associated with it but only allocates a 12 Byte (32bit) block with the IMT. Since IShared<T> is not a regular interface but an anonymous method you can directly access the members of the underlying type. Yes, there is a method call every time but as you can measure that does not cause any significant overhead (unless you call .Add a million times). And even then the actual work being performed totally outweighs the smart pointer overhead