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