unit Myc.Core.Lazy; interface uses System.SysUtils, Myc.Signals, Myc.Lazy; type TMycNullMutable = class(TInterfacedObject, TMutable.IMutable) protected function GetChanged: TSignal; function GetValue: T; end; TMycMutableBase = class(TInterfacedObject, TMutable.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 = class(TMycMutableBase) private FProc: TFunc; protected function GetValue: T; override; public constructor Create(const AChanged: TSignal; const AProc: TFunc); end; TMycWriteableMutable = class(TInterfacedObject, TMutable.IMutable, TMutable.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 = class(TInterfacedObject, TLazy.ILazy) protected function GetChanged: TState; public function Pop(out Res: T): Boolean; end; TMycLazyBase = class(TInterfacedObject, TLazy.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 = class(TMycLazyBase) private FProc: TFunc; protected function GetValue: T; override; public constructor Create(const AChanged: TState; const AProc: TFunc); end; TMycChainedLazy = class(TMycLazyBase) private FValue: TLazy.ILazy; protected function GetValue: T; override; public constructor Create(const AValue: TLazy.ILazy); end; implementation { TMycNullMutable } function TMycNullMutable.GetChanged: TSignal; begin Result := TSignal.Null; end; function TMycNullMutable.GetValue: T; begin Result := Default(T); end; { TMycMutableBase } constructor TMycMutableBase.Create(const AChanged: TSignal); begin inherited Create; FChanged := TEvent.CreateEvent; FChangeState := AChanged.Subscribe(FChanged); end; destructor TMycMutableBase.Destroy; begin FChangeState.Unsubscribe; inherited; end; function TMycMutableBase.GetChanged: TSignal; begin Result := FChanged.Signal; end; { TMycWriteableMutable } constructor TMycWriteableMutable.Create(const AValue: T); begin inherited Create; FValue := AValue; FChanged := TEvent.CreateEvent; end; function TMycWriteableMutable.GetChanged: TSignal; begin Result := FChanged.Signal; end; function TMycWriteableMutable.GetValue: T; begin Result := FValue; end; procedure TMycWriteableMutable.SetValue(const Value: T); begin FValue := Value; FChanged.Notify; end; { TMycNullLazy } function TMycNullLazy.GetChanged: TState; begin Result := TState.Null; end; function TMycNullLazy.Pop(out Res: T): Boolean; begin Res := Default(T); Result := true; end; { TMycLazyBase } constructor TMycLazyBase.Create(const AChanged: TState); begin inherited Create; FChanged := TFlag.CreateFlag; FChangeState := AChanged.Subscribe(FChanged); end; destructor TMycLazyBase.Destroy; begin FChangeState.Unsubscribe; inherited; end; function TMycLazyBase.GetChanged: TState; begin Result := FChanged.State; end; function TMycLazyBase.Pop(out Res: T): Boolean; begin Result := FChanged.State.IsSet; if Result then begin Res := GetValue; FChanged.Reset; end; end; { TMycFuncLazy } constructor TMycFuncLazy.Create(const AChanged: TState; const AProc: TFunc); begin inherited Create(AChanged); FProc := AProc; Assert(Assigned(FProc)); end; function TMycFuncLazy.GetValue: T; begin Result := FProc(); end; { TMycChainedLazy } constructor TMycChainedLazy.Create(const AValue: TLazy.ILazy); begin inherited Create(AValue.Changed); FValue := AValue; end; function TMycChainedLazy.GetValue: T; begin if not FValue.Pop(Result) then raise Exception.Create('Lazy chain already popped'); end; constructor TMycFuncMutable.Create(const AChanged: TSignal; const AProc: TFunc); begin inherited Create(AChanged); FProc := AProc; end; function TMycFuncMutable.GetValue: T; begin Result := FProc(); end; end.