I have this atomic optimistic initializer class:
type
Atomic<T: IInterface> = class
type TFactory = reference to function: T;
class function Initialize(var storage: T; factory: TFactory): T;
end;
class function Atomic<T>.Initialize(var storage: T; factory: TFactory): T;
var
tmpIntf: T;
begin
if not assigned(storage) then begin
tmpIntf := factory();
if InterlockedCompareExchangePointer(PPointer(@storage)^, PPointer(@tmpIntf)^, nil) = nil then
PPointer(@tmpIntf)^ := nil;
end;
Result := storage;
end;
Now I would like to implement the same pattern for objects.
type
Atomic<T: class> = class
type TFactory = reference to function: T;
class function Initialize(var storage: T; factory: TFactory): T;
end;
class function Atomic<T>.Initialize(var storage: T; factory: TFactory): T;
var
tmpIntf: T;
begin
if not assigned(storage) then begin
tmpIntf := factory();
if InterlockedCompareExchangePointer(PPointer(@storage)^, PPointer(@tmpIntf)^, nil) = nil then
tmpIntf.Free;
end;
Result := storage;
end;
I can do those two in two separate classes, but I would really like to put both initializers under the same umbrella. IOW, I would ideally like to use this as
var
o: TObject;
i: IInterface;
Atomic<TObject>.Initialize(o, CreateObject);
Atomic<IInterface>.Initialize(i, CreateInterface);
I can't find any good solution for this. The only idea I got is to declare class as Atomic<T>
(without constraints) and then somehow (don't yet know how) check the RTTI of T in runtime and proceed accordingly.
I don't like this idea much and I'm looking for a better approach.