ProtectedMutable
This commit is contained in:
+33
-55
@@ -45,8 +45,8 @@ type
|
|||||||
SymbolsComboBox: TComboBox;
|
SymbolsComboBox: TComboBox;
|
||||||
LoadButton: TButton;
|
LoadButton: TButton;
|
||||||
FlowLayout: TFlowLayout;
|
FlowLayout: TFlowLayout;
|
||||||
ChartButton: TButton;
|
ChartButton: TButton;
|
||||||
StopButton: TButton;
|
StopButton: TButton;
|
||||||
procedure RandomButtonClick(Sender: TObject);
|
procedure RandomButtonClick(Sender: TObject);
|
||||||
procedure FormCreate(Sender: TObject);
|
procedure FormCreate(Sender: TObject);
|
||||||
procedure FormDestroy(Sender: TObject);
|
procedure FormDestroy(Sender: TObject);
|
||||||
@@ -214,36 +214,41 @@ begin
|
|||||||
|
|
||||||
var Symbol := FSymbols.WaitFor[SymbolsComboBox.ItemIndex];
|
var Symbol := FSymbols.WaitFor[SymbolsComboBox.ItemIndex];
|
||||||
|
|
||||||
var currPathData := TMutable<IObjectRef<TPathData>>.CreateProtected;
|
var currPathData := TMutable<IObjectRef<TPathData>>.CreateWriteable.Protect;
|
||||||
var currLog := TMutable<String>.CreateProtected;
|
var currLog := TMutable<String>.CreateWriteable.Protect;
|
||||||
|
|
||||||
const width = 1000;
|
const width = 1000;
|
||||||
const incsize = 100;
|
const incsize = 100;
|
||||||
begin
|
|
||||||
var arr := TDataSeries<TAskBidItem>.CreateWriteable(width);
|
|
||||||
var done :=
|
|
||||||
FServer.ProcessData(
|
|
||||||
Symbol,
|
|
||||||
FTerminate.Signal,
|
|
||||||
procedure(const Values: TArray<TDataPoint<TAskBidItem>>; const Terminated: TState)
|
|
||||||
begin
|
|
||||||
arr.Add(Values);
|
|
||||||
currLog.Value := arr.TotalCount.ToString;
|
|
||||||
|
|
||||||
var PathData := TPathData.Create;
|
TaskManager.RunTask(
|
||||||
var Prices := arr;
|
nil,
|
||||||
if Prices.Count > 0 then
|
procedure
|
||||||
|
begin
|
||||||
|
var arr := TDataSeries<TAskBidItem>.CreateWriteable(width);
|
||||||
|
var done :=
|
||||||
|
FServer.ProcessData(
|
||||||
|
Symbol,
|
||||||
|
FTerminate.Signal,
|
||||||
|
procedure(const Values: TArray<TDataPoint<TAskBidItem>>; const Terminated: TState)
|
||||||
begin
|
begin
|
||||||
PathData.MoveTo(PointF(Prices.Count - 1, Prices[0].Data.Ask));
|
arr.Add(Values);
|
||||||
for var i := 1 to Prices.Count - 1 do
|
currLog.Value := arr.TotalCount.ToString;
|
||||||
PathData.LineTo(PointF(Prices.Count - i - 1, Prices[i].Data.Ask));
|
|
||||||
end;
|
|
||||||
|
|
||||||
currPathData.Value := TObjectRef<TPathData>.Create(PathData);
|
var PathData := TPathData.Create;
|
||||||
end
|
var Prices := arr;
|
||||||
);
|
if Prices.Count > 0 then
|
||||||
FLoadDone := TState.All([FLoadDone, done]);
|
begin
|
||||||
end;
|
PathData.MoveTo(PointF(Prices.Count - 1, Prices[0].Data.Ask));
|
||||||
|
for var i := 1 to Prices.Count - 1 do
|
||||||
|
PathData.LineTo(PointF(Prices.Count - i - 1, Prices[i].Data.Ask));
|
||||||
|
end;
|
||||||
|
|
||||||
|
currPathData.Value := TObjectRef<TPathData>.Create(PathData);
|
||||||
|
end
|
||||||
|
);
|
||||||
|
FLoadDone := TState.All([FLoadDone, done]);
|
||||||
|
end
|
||||||
|
);
|
||||||
|
|
||||||
LogMemo.AddIdleHandler(currLog.Changed, procedure begin LogMemo.Lines.Add(Symbol + ': ' + currLog.Value); end);
|
LogMemo.AddIdleHandler(currLog.Changed, procedure begin LogMemo.Lines.Add(Symbol + ': ' + currLog.Value); end);
|
||||||
|
|
||||||
@@ -251,39 +256,12 @@ begin
|
|||||||
currPathData.Changed,
|
currPathData.Changed,
|
||||||
procedure
|
procedure
|
||||||
begin
|
begin
|
||||||
if currPathData.Value<>nil then
|
if currPathData.Value <> nil then
|
||||||
begin
|
begin
|
||||||
Path1.Data.Assign( currPathData.Value.Obj );
|
Path1.Data.Assign(currPathData.Value.Obj);
|
||||||
end;
|
|
||||||
end );
|
|
||||||
|
|
||||||
|
|
||||||
(*
|
|
||||||
FLoadDone := TState.All([FLoadDone, done]);
|
|
||||||
|
|
||||||
Path1.AddIdleHandler(
|
|
||||||
curr.Changed,
|
|
||||||
procedure
|
|
||||||
begin
|
|
||||||
var Prices := curr.Value;
|
|
||||||
|
|
||||||
if Prices.Count > 0 then
|
|
||||||
begin
|
|
||||||
Path1.BeginUpdate;
|
|
||||||
try
|
|
||||||
Path1.Data.Clear;
|
|
||||||
Path1.Data.MoveTo(PointF(Path1.Width - 1, Prices[0].Data.Ask));
|
|
||||||
for var i := 1 to Prices.Count - 1 do
|
|
||||||
begin
|
|
||||||
Path1.Data.LineTo(PointF(Path1.Width - i - 1, Prices[i].Data.Ask));
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
Path1.EndUpdate;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
);
|
);
|
||||||
*)
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
+41
-22
@@ -46,6 +46,7 @@ type
|
|||||||
function GetChanged: TSignal;
|
function GetChanged: TSignal;
|
||||||
function GetValue: T;
|
function GetValue: T;
|
||||||
function GetWriter: TMutable<T>.IWriter;
|
function GetWriter: TMutable<T>.IWriter;
|
||||||
|
function Exchange(const Value: T): T;
|
||||||
public
|
public
|
||||||
constructor Create(const AValue: T);
|
constructor Create(const AValue: T);
|
||||||
procedure SetValue(const Value: T);
|
procedure SetValue(const Value: T);
|
||||||
@@ -80,19 +81,19 @@ type
|
|||||||
constructor Create(const AChanged: TSignal.ISignal; const AProc: TFunc<T>);
|
constructor Create(const AChanged: TSignal.ISignal; const AProc: TFunc<T>);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TMycProtectedWriteableMutable<T> = class(TInterfacedObject, TMutable<T>.IMutable, TMutable<T>.IWriter)
|
TMycProtectedMutable<T> = class(TInterfacedObject, TMutable<T>.IMutable, TMutable<T>.IWriter)
|
||||||
private
|
private
|
||||||
FValue: T;
|
FMutable: TMutable<T>.IMutable;
|
||||||
FChanged: TEvent;
|
|
||||||
FLock: Integer;
|
FLock: Integer;
|
||||||
protected
|
protected
|
||||||
|
function Exchange(const Value: T): T;
|
||||||
function GetChanged: TSignal;
|
function GetChanged: TSignal;
|
||||||
function GetValue: T;
|
function GetValue: T;
|
||||||
function GetWriter: TMutable<T>.IWriter;
|
function GetWriter: TMutable<T>.IWriter;
|
||||||
procedure Lock; inline;
|
procedure Lock; inline;
|
||||||
procedure Release; inline;
|
procedure Release; inline;
|
||||||
public
|
public
|
||||||
constructor Create(const AValue: T);
|
constructor Create(const AMutable: TMutable<T>.IMutable);
|
||||||
procedure SetValue(const Value: T);
|
procedure SetValue(const Value: T);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -149,6 +150,12 @@ begin
|
|||||||
FChanged := TEvent.CreateEvent;
|
FChanged := TEvent.CreateEvent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TMycWriteableMutable<T>.Exchange(const Value: T): T;
|
||||||
|
begin
|
||||||
|
Result := FValue;
|
||||||
|
FValue := Value;
|
||||||
|
end;
|
||||||
|
|
||||||
function TMycWriteableMutable<T>.GetChanged: TSignal;
|
function TMycWriteableMutable<T>.GetChanged: TSignal;
|
||||||
begin
|
begin
|
||||||
Result := FChanged.Signal;
|
Result := FChanged.Signal;
|
||||||
@@ -239,52 +246,64 @@ begin
|
|||||||
Result := FProc();
|
Result := FProc();
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TMycProtectedWriteableMutable<T> }
|
{ TMycProtectedMutable<T> }
|
||||||
|
|
||||||
constructor TMycProtectedWriteableMutable<T>.Create(const AValue: T);
|
constructor TMycProtectedMutable<T>.Create(const AMutable: TMutable<T>.IMutable);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
FValue := AValue;
|
FMutable := AMutable;
|
||||||
FChanged := TEvent.CreateEvent;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMycProtectedWriteableMutable<T>.GetChanged: TSignal;
|
function TMycProtectedMutable<T>.Exchange(const Value: T): T;
|
||||||
begin
|
|
||||||
Result := FChanged.Signal;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TMycProtectedWriteableMutable<T>.GetValue: T;
|
|
||||||
begin
|
begin
|
||||||
Lock;
|
Lock;
|
||||||
try
|
try
|
||||||
Result := FValue;
|
Assert(FMutable.Writer <> nil);
|
||||||
|
FMutable.Writer.Exchange(Value);
|
||||||
finally
|
finally
|
||||||
Release;
|
Release;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMycProtectedWriteableMutable<T>.GetWriter: TMutable<T>.IWriter;
|
function TMycProtectedMutable<T>.GetChanged: TSignal;
|
||||||
begin
|
begin
|
||||||
Result := Self;
|
Result := FMutable.Changed;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMycProtectedWriteableMutable<T>.Lock;
|
function TMycProtectedMutable<T>.GetValue: T;
|
||||||
|
begin
|
||||||
|
Lock;
|
||||||
|
try
|
||||||
|
Result := FMutable.Value;
|
||||||
|
finally
|
||||||
|
Release;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMycProtectedMutable<T>.GetWriter: TMutable<T>.IWriter;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
if FMutable.Writer <> nil then
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMycProtectedMutable<T>.Lock;
|
||||||
begin
|
begin
|
||||||
while AtomicExchange(FLock, 1) = 1 do
|
while AtomicExchange(FLock, 1) = 1 do
|
||||||
YieldProcessor;
|
YieldProcessor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMycProtectedWriteableMutable<T>.Release;
|
procedure TMycProtectedMutable<T>.Release;
|
||||||
begin
|
begin
|
||||||
AtomicExchange(FLock, 0);
|
AtomicExchange(FLock, 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMycProtectedWriteableMutable<T>.SetValue(const Value: T);
|
procedure TMycProtectedMutable<T>.SetValue(const Value: T);
|
||||||
begin
|
begin
|
||||||
Lock;
|
Lock;
|
||||||
try
|
try
|
||||||
FValue := Value;
|
Assert(FMutable.Writer <> nil);
|
||||||
FChanged.Notify;
|
FMutable.Writer.SetValue(Value);
|
||||||
finally
|
finally
|
||||||
Release;
|
Release;
|
||||||
end;
|
end;
|
||||||
|
|||||||
+1
-1
@@ -180,7 +180,7 @@ end;
|
|||||||
function TObjectRef<T>.Pop: T;
|
function TObjectRef<T>.Pop: T;
|
||||||
begin
|
begin
|
||||||
Result := FObj;
|
Result := FObj;
|
||||||
FreeAndNil( FObj );
|
FreeAndNil(FObj);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
+14
-9
@@ -11,6 +11,7 @@ type
|
|||||||
type
|
type
|
||||||
IWriter = interface
|
IWriter = interface
|
||||||
procedure SetValue(const Value: T);
|
procedure SetValue(const Value: T);
|
||||||
|
function Exchange(const Value: T): T;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
IMutable = interface
|
IMutable = interface
|
||||||
@@ -46,9 +47,10 @@ type
|
|||||||
class property Null: IMutable read FNull;
|
class property Null: IMutable read FNull;
|
||||||
|
|
||||||
class function Construct(const Changing: TSignal; const Proc: TFunc<T>): TMutable<T>; overload; static;
|
class function Construct(const Changing: TSignal; const Proc: TFunc<T>): TMutable<T>; overload; static;
|
||||||
class function CreateProtected: TMutable<T>; overload; static;
|
|
||||||
class function CreateWriteable: TMutable<T>; overload; static;
|
class function CreateWriteable: TMutable<T>; overload; static;
|
||||||
|
|
||||||
|
function Protect: TMutable<T>;
|
||||||
|
|
||||||
property Value: T read GetValue write SetValue;
|
property Value: T read GetValue write SetValue;
|
||||||
property Changed: TSignal read GetChanged;
|
property Changed: TSignal read GetChanged;
|
||||||
property IsWriteable: Boolean read GetIsWriteable;
|
property IsWriteable: Boolean read GetIsWriteable;
|
||||||
@@ -112,11 +114,6 @@ begin
|
|||||||
Result := TMycFuncMutable<T>.Create(Changing, Proc);
|
Result := TMycFuncMutable<T>.Create(Changing, Proc);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TMutable<T>.CreateProtected: TMutable<T>;
|
|
||||||
begin
|
|
||||||
Result := TMycProtectedWriteableMutable<T>.Create(Default(T));
|
|
||||||
end;
|
|
||||||
|
|
||||||
class function TMutable<T>.CreateWriteable: TMutable<T>;
|
class function TMutable<T>.CreateWriteable: TMutable<T>;
|
||||||
begin
|
begin
|
||||||
Result := TMycWriteableMutable<T>.Create(Default(T));
|
Result := TMycWriteableMutable<T>.Create(Default(T));
|
||||||
@@ -129,7 +126,7 @@ end;
|
|||||||
|
|
||||||
function TMutable<T>.GetIsWriteable: Boolean;
|
function TMutable<T>.GetIsWriteable: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := Assigned( FMutable.Writer );
|
Result := Assigned(FMutable.Writer);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMutable<T>.GetValue: T;
|
function TMutable<T>.GetValue: T;
|
||||||
@@ -137,10 +134,18 @@ begin
|
|||||||
Result := FMutable.Value;
|
Result := FMutable.Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TMutable<T>.Protect: TMutable<T>;
|
||||||
|
begin
|
||||||
|
if not (FMutable is TMycProtectedMutable<T>) then
|
||||||
|
Result := TMycProtectedMutable<T>.Create(FMutable)
|
||||||
|
else
|
||||||
|
Result := FMutable;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TMutable<T>.SetValue(const Value: T);
|
procedure TMutable<T>.SetValue(const Value: T);
|
||||||
begin
|
begin
|
||||||
Assert( IsWriteable );
|
Assert(IsWriteable);
|
||||||
FMutable.Writer.SetValue( Value );
|
FMutable.Writer.SetValue(Value);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class operator TMutable<T>.Implicit(const A: TMutable<T>): IMutable;
|
class operator TMutable<T>.Implicit(const A: TMutable<T>): IMutable;
|
||||||
|
|||||||
@@ -116,13 +116,13 @@ end;
|
|||||||
|
|
||||||
procedure TDataSeries<T>.Add(const Data: array of TDataPoint<T>; NumToAdd: Integer = -1);
|
procedure TDataSeries<T>.Add(const Data: array of TDataPoint<T>; NumToAdd: Integer = -1);
|
||||||
begin
|
begin
|
||||||
Assert( IsWriteable );
|
Assert(IsWriteable);
|
||||||
FDataSeries.Writer.Add( Data, NumToAdd );
|
FDataSeries.Writer.Add(Data, NumToAdd);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDataSeries<T>.Clear;
|
procedure TDataSeries<T>.Clear;
|
||||||
begin
|
begin
|
||||||
Assert( IsWriteable );
|
Assert(IsWriteable);
|
||||||
FDataSeries.Writer.Clear;
|
FDataSeries.Writer.Clear;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ end;
|
|||||||
|
|
||||||
function TDataSeries<T>.GetIsWriteable: Boolean;
|
function TDataSeries<T>.GetIsWriteable: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := Assigned( FDataSeries.Writer );
|
Result := Assigned(FDataSeries.Writer);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDataSeries<T>.GetTime(Idx: Int64): TDateTime;
|
function TDataSeries<T>.GetTime(Idx: Int64): TDateTime;
|
||||||
|
|||||||
@@ -101,8 +101,12 @@ type
|
|||||||
// Used by cache to actually load an uncached file.
|
// Used by cache to actually load an uncached file.
|
||||||
function DoLoad(const FileName: string): TFuture<TArray<TDataPoint<T>>>;
|
function DoLoad(const FileName: string): TFuture<TArray<TDataPoint<T>>>;
|
||||||
|
|
||||||
function ProcessFile(FileInfo: TAuraDataFile; const DataFile: TFuture<TArray<TDataPoint<T>>>; Terminated: TState; Proc: TDataProc<T>):
|
function ProcessFile(
|
||||||
TState;
|
FileInfo: TAuraDataFile;
|
||||||
|
const DataFile: TFuture<TArray<TDataPoint<T>>>;
|
||||||
|
Terminated: TState;
|
||||||
|
Proc: TDataProc<T>
|
||||||
|
): TState;
|
||||||
|
|
||||||
strict private
|
strict private
|
||||||
class var
|
class var
|
||||||
@@ -394,10 +398,10 @@ begin
|
|||||||
Result :=
|
Result :=
|
||||||
FindFirstFile(Symbol)
|
FindFirstFile(Symbol)
|
||||||
.Chain(
|
.Chain(
|
||||||
function(const FirstFileInfo: TAuraDataFile): TState
|
function(const FirstFileInfo: TAuraDataFile): TState
|
||||||
begin
|
begin
|
||||||
Result := ProcessFile(FirstFileInfo, LoadDataFile(FirstFileInfo), terminated, capProc);
|
Result := ProcessFile(FirstFileInfo, LoadDataFile(FirstFileInfo), terminated, capProc);
|
||||||
end);
|
end);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAuraDataServer<T>.LoadDataFile(const DataFile: TAuraDataFile): TFuture<TArray<TDataPoint<T>>>;
|
function TAuraDataServer<T>.LoadDataFile(const DataFile: TAuraDataFile): TFuture<TArray<TDataPoint<T>>>;
|
||||||
@@ -406,15 +410,19 @@ begin
|
|||||||
Result := FCachedFiles.GetOrAdd(DataFile.GetFullFileName);
|
Result := FCachedFiles.GetOrAdd(DataFile.GetFullFileName);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAuraDataServer<T>.ProcessFile(FileInfo: TAuraDataFile; const DataFile: TFuture<TArray<TDataPoint<T>>>; Terminated: TState; Proc:
|
function TAuraDataServer<T>.ProcessFile(
|
||||||
TDataProc<T>): TState;
|
FileInfo: TAuraDataFile;
|
||||||
|
const DataFile: TFuture<TArray<TDataPoint<T>>>;
|
||||||
|
Terminated: TState;
|
||||||
|
Proc: TDataProc<T>
|
||||||
|
): TState;
|
||||||
begin
|
begin
|
||||||
if not FileInfo.IsValid or Terminated.IsSet then
|
if not FileInfo.IsValid or Terminated.IsSet then
|
||||||
exit(TState.Null);
|
exit(TState.Null);
|
||||||
|
|
||||||
// Read ahead the next file, while processing the current one
|
// Read ahead the next file, while processing the current one
|
||||||
var nextFileInfo := FileInfo.GetNextFile;
|
var nextFileInfo := FileInfo.GetNextFile;
|
||||||
var nextFile := LoadDataFile( nextFileInfo );
|
var nextFile := LoadDataFile(nextFileInfo);
|
||||||
|
|
||||||
Result :=
|
Result :=
|
||||||
DataFile.Chain(
|
DataFile.Chain(
|
||||||
|
|||||||
Reference in New Issue
Block a user