Files
MycLib/Src/Myc.Core.Lazy.pas
T
2025-07-12 12:11:16 +02:00

279 lines
6.2 KiB
ObjectPascal

unit Myc.Core.Lazy;
interface
uses
System.Classes,
System.SysUtils,
System.SyncObjs,
Myc.Signals,
Myc.Lazy;
type
TMycNullMutable<T> = class(TInterfacedObject, TMutable<T>.IMutable)
private
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, TWriteable<T>.IWriteable)
private
FValue: T;
FChanged: TEvent;
protected
function GetChanged: TSignal;
function GetValue: T;
function Exchange(const Value: T): 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: TSignal);
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: TSignal.ISignal; const AProc: TFunc<T>);
end;
TMycProtectedMutable<T> = class(TInterfacedObject, TMutable<T>.IMutable, TWriteable<T>.IWriteable)
private
FWriteable: TWriteable<T>.IWriteable;
FLock: TLightweightMREW;
protected
function Exchange(const Value: T): T;
function GetChanged: TSignal;
function GetValue: T;
public
constructor Create(const AWriteable: TWriteable<T>.IWriteable);
procedure SetValue(const Value: T);
end;
implementation
uses
System.Generics.Defaults;
{ 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>.Exchange(const Value: T): T;
begin
Result := FValue;
FValue := Value;
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
if not TEqualityComparer<T>.Default.Equals(FValue, Value) then
begin
FValue := Value;
FChanged.Notify;
end;
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: TSignal);
begin
inherited Create;
FChanged := TFlag.CreateFlag;
FChanged.Notify;
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: TSignal.ISignal; const AProc: TFunc<T>);
begin
inherited Create(AChanged);
FProc := AProc;
Assert(Assigned(FProc));
end;
function TMycFuncLazy<T>.GetValue: T;
begin
Result := FProc();
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;
{ TMycProtectedMutable<T> }
constructor TMycProtectedMutable<T>.Create(const AWriteable: TWriteable<T>.IWriteable);
begin
inherited Create;
FWriteable := AWriteable;
end;
function TMycProtectedMutable<T>.Exchange(const Value: T): T;
begin
FLock.BeginWrite;
try
Result := FWriteable.Exchange(Value);
finally
FLock.EndWrite;
end;
end;
function TMycProtectedMutable<T>.GetChanged: TSignal;
begin
Result := FWriteable.Changed;
end;
function TMycProtectedMutable<T>.GetValue: T;
begin
FLock.BeginRead;
try
Result := FWriteable.Value;
finally
FLock.EndRead;
end;
end;
procedure TMycProtectedMutable<T>.SetValue(const Value: T);
begin
FLock.BeginWrite;
try
FWriteable.SetValue(Value);
finally
Flock.EndWrite;
end;
end;
end.