Files
MycLib/Src/Myc.Core.Lazy.pas
T
Michael Schimmel c4d8607d17 TMutable
2025-06-06 01:22:25 +02:00

230 lines
5.0 KiB
ObjectPascal

unit Myc.Core.Lazy;
interface
uses
System.SysUtils,
Myc.Signals,
Myc.Lazy;
type
TMycNullMutable<T> = class(TInterfacedObject, TMutable<T>.IMutable)
protected
function GetChanged: TSignal;
function GetValue: T;
end;
TMycMutableBase<T> = class(TInterfacedObject, TMutable<T>.IMutable)
strict private
FChanged: TEvent;
FChangeState: TSignal.TSubscription;
function GetChanged: TSignal;
protected
function GetValue: T; virtual; abstract;
public
constructor Create(const AChanged: TSignal);
destructor Destroy; override;
end;
TMycFuncMutable<T> = class(TMycMutableBase<T>)
private
FProc: TFunc<T>;
protected
function GetValue: T; override;
public
constructor Create(const AChanged: TSignal; const AProc: TFunc<T>);
end;
TMycWriteableMutable<T> = class(TInterfacedObject, TMutable<T>.IMutable, TMutable<T>.IWriteableMutable)
private
FValue: T;
FChanged: TEvent;
protected
function GetChanged: TSignal;
function GetValue: T;
public
constructor Create(const AValue: T);
procedure SetValue(const Value: T);
end;
TMycNullLazy<T> = class(TInterfacedObject, TLazy<T>.ILazy)
protected
function GetChanged: TState;
public
function Pop(out Res: T): Boolean;
end;
TMycLazyBase<T> = class(TInterfacedObject, TLazy<T>.ILazy)
strict private
FChanged: TFlag;
FChangeState: TSignal.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: TLazy<T>.ILazy;
protected
function GetValue: T; override;
public
constructor Create(const AValue: TLazy<T>.ILazy);
end;
implementation
{ TMycNullMutable<T> }
function TMycNullMutable<T>.GetChanged: TSignal;
begin
Result := TSignal.Null;
end;
function TMycNullMutable<T>.GetValue: T;
begin
Result := Default(T);
end;
{ TMycMutableBase<T> }
constructor TMycMutableBase<T>.Create(const AChanged: TSignal);
begin
inherited Create;
FChanged := TEvent.CreateEvent;
FChangeState := AChanged.Subscribe(FChanged);
end;
destructor TMycMutableBase<T>.Destroy;
begin
FChangeState.Unsubscribe;
inherited;
end;
function TMycMutableBase<T>.GetChanged: TSignal;
begin
Result := FChanged.Signal;
end;
{ TMycWriteableMutable<T> }
constructor TMycWriteableMutable<T>.Create(const AValue: T);
begin
inherited Create;
FValue := AValue;
FChanged := TEvent.CreateEvent;
end;
function TMycWriteableMutable<T>.GetChanged: TSignal;
begin
Result := FChanged.Signal;
end;
function TMycWriteableMutable<T>.GetValue: T;
begin
Result := FValue;
end;
procedure TMycWriteableMutable<T>.SetValue(const Value: T);
begin
FValue := Value;
FChanged.Notify;
end;
{ 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: TLazy<T>.ILazy);
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;
constructor TMycFuncMutable<T>.Create(const AChanged: TSignal; const AProc: TFunc<T>);
begin
inherited Create(AChanged);
FProc := AProc;
end;
function TMycFuncMutable<T>.GetValue: T;
begin
Result := FProc();
end;
end.