У меня есть этот атомарный оптимистичный класс инициализатора:
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;
Теперь я хотел бы реализовать тот же шаблон для объектов.
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;
Я могу сделать это вдвоем за два. отдельные классы, но я бы действительно хотел поместить оба инициализатора под один и тот же зонтик. IOW, я бы в идеале использовал это как
var
o: TObject;
i: IInterface;
Atomic<TObject>.Initialize(o, CreateObject);
Atomic<IInterface>.Initialize(i, CreateInterface);
Я не могу найти для этого никакого хорошего решения. Единственная идея, которую я получил, - это объявить класс как Atomic
(без ограничений), а затем каким-то образом (пока не знаю как) проверить RTTI T во время выполнения и действовать соответственно.
Мне эта идея не очень нравится, и я Я ищу лучший подход.