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