123 lines
2.6 KiB
ObjectPascal
123 lines
2.6 KiB
ObjectPascal
unit Myc.Core.Lazy;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
Myc.Signals,
|
|
Myc.Lazy;
|
|
|
|
type
|
|
TMycNullLazy<T> = class(TInterfacedObject, IMycLazy<T>)
|
|
protected
|
|
function GetChanged: TState;
|
|
public
|
|
function Pop(out Res: T): Boolean;
|
|
end;
|
|
|
|
TMycLazyBase<T> = class(TInterfacedObject, IMycLazy<T>)
|
|
strict private
|
|
FChanged: TFlag;
|
|
FChangeState: TSubscription;
|
|
function GetChanged: TState;
|
|
protected
|
|
function GetValue: T; virtual; abstract;
|
|
public
|
|
constructor Create(const AChanged: TState);
|
|
destructor Destroy; override;
|
|
function Pop(out Res: T): Boolean;
|
|
end;
|
|
|
|
TMycFuncLazy<T> = class(TMycLazyBase<T>)
|
|
private
|
|
FProc: TFunc<T>;
|
|
protected
|
|
function GetValue: T; override;
|
|
public
|
|
constructor Create(const AChanged: TState; const AProc: TFunc<T>);
|
|
end;
|
|
|
|
TMycChainedLazy<T> = class(TMycLazyBase<T>)
|
|
private
|
|
FValue: IMycLazy<T>;
|
|
protected
|
|
function GetValue: T; override;
|
|
public
|
|
constructor Create(const AValue: IMycLazy<T>);
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TMycNullLazy<T> }
|
|
|
|
function TMycNullLazy<T>.GetChanged: TState;
|
|
begin
|
|
Result := TState.Null;
|
|
end;
|
|
|
|
function TMycNullLazy<T>.Pop(out Res: T): Boolean;
|
|
begin
|
|
Res := Default(T);
|
|
Result := true;
|
|
end;
|
|
|
|
{ TMycLazyBase<T> }
|
|
|
|
constructor TMycLazyBase<T>.Create(const AChanged: TState);
|
|
begin
|
|
inherited Create;
|
|
FChanged := TFlag.CreateFlag;
|
|
FChangeState := AChanged.Subscribe(FChanged);
|
|
end;
|
|
|
|
destructor TMycLazyBase<T>.Destroy;
|
|
begin
|
|
FChangeState.Unsubscribe;
|
|
inherited;
|
|
end;
|
|
|
|
function TMycLazyBase<T>.GetChanged: TState;
|
|
begin
|
|
Result := FChanged.State;
|
|
end;
|
|
|
|
function TMycLazyBase<T>.Pop(out Res: T): Boolean;
|
|
begin
|
|
Result := FChanged.State.IsSet;
|
|
if Result then
|
|
begin
|
|
Res := GetValue;
|
|
FChanged.Reset;
|
|
end;
|
|
end;
|
|
|
|
{ TMycFuncLazy<T> }
|
|
|
|
constructor TMycFuncLazy<T>.Create(const AChanged: TState; const AProc: TFunc<T>);
|
|
begin
|
|
inherited Create(AChanged);
|
|
FProc := AProc;
|
|
Assert( Assigned(FProc) );
|
|
end;
|
|
|
|
function TMycFuncLazy<T>.GetValue: T;
|
|
begin
|
|
Result := FProc();
|
|
end;
|
|
|
|
{ TMycChainedLazy<T> }
|
|
|
|
constructor TMycChainedLazy<T>.Create(const AValue: IMycLazy<T>);
|
|
begin
|
|
inherited Create(AValue.Changed);
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TMycChainedLazy<T>.GetValue: T;
|
|
begin
|
|
if not FValue.Pop(Result) then
|
|
raise Exception.Create('Lazy chain already popped');
|
|
end;
|
|
|
|
end.
|