TWriteable<T>
This commit is contained in:
@@ -89,15 +89,14 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
|
|
||||||
var arr := TDataSeries<TAskBidItem>.CreateArray(3000);
|
var arr := TDataSeries<TAskBidItem>.CreateArray(3000);
|
||||||
var curr := TMutable<TDataSeries<TAskBidItem>>.CreateProtected;
|
var curr := TWriteable<TDataSeries<TAskBidItem>>.CreateProtected;
|
||||||
var Symbol := FSymbols.WaitFor[SymbolsComboBox.ItemIndex];
|
var Symbol := FSymbols.WaitFor[SymbolsComboBox.ItemIndex];
|
||||||
|
|
||||||
var done :=
|
var done :=
|
||||||
TAuraFileLoader<TAskBidItem>.LoadData(
|
FServer.ProcessData(
|
||||||
FServer as TAuraTABFileServer,
|
|
||||||
Symbol,
|
Symbol,
|
||||||
FTerminate.Signal,
|
FTerminate.Signal,
|
||||||
procedure(const Values: TArray<TDataPoint<TAskBidItem>>)
|
procedure(const Values: TArray<TDataPoint<TAskBidItem>>; const Terminated: TState)
|
||||||
begin
|
begin
|
||||||
arr.Add(Values);
|
arr.Add(Values);
|
||||||
curr.Value := arr.Copy;
|
curr.Value := arr.Copy;
|
||||||
|
|||||||
+19
-8
@@ -36,7 +36,7 @@ type
|
|||||||
constructor Create(const AChanged: TSignal; const AProc: TFunc<T>);
|
constructor Create(const AChanged: TSignal; const AProc: TFunc<T>);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TMycWriteableMutable<T> = class(TInterfacedObject, TMutable<T>.IMutable, TMutable<T>.IWriteable)
|
TMycWriteableMutable<T> = class(TInterfacedObject, TMutable<T>.IMutable, TWriteable<T>.IWriteable)
|
||||||
private
|
private
|
||||||
FValue: T;
|
FValue: T;
|
||||||
FChanged: TEvent;
|
FChanged: TEvent;
|
||||||
@@ -77,7 +77,7 @@ 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>.IWriteable)
|
TMycProtectedWriteableMutable<T> = class(TInterfacedObject, TMutable<T>.IMutable, TWriteable<T>.IWriteable)
|
||||||
private
|
private
|
||||||
FValue: T;
|
FValue: T;
|
||||||
FChanged: TEvent;
|
FChanged: TEvent;
|
||||||
@@ -85,6 +85,8 @@ type
|
|||||||
protected
|
protected
|
||||||
function GetChanged: TSignal;
|
function GetChanged: TSignal;
|
||||||
function GetValue: T;
|
function GetValue: T;
|
||||||
|
procedure Lock; inline;
|
||||||
|
procedure Release; inline;
|
||||||
public
|
public
|
||||||
constructor Create(const AValue: T);
|
constructor Create(const AValue: T);
|
||||||
procedure SetValue(const Value: T);
|
procedure SetValue(const Value: T);
|
||||||
@@ -234,24 +236,33 @@ end;
|
|||||||
|
|
||||||
function TMycProtectedWriteableMutable<T>.GetValue: T;
|
function TMycProtectedWriteableMutable<T>.GetValue: T;
|
||||||
begin
|
begin
|
||||||
while AtomicExchange(FLock, 1) = 1 do
|
Lock;
|
||||||
YieldProcessor;
|
|
||||||
try
|
try
|
||||||
Result := FValue;
|
Result := FValue;
|
||||||
finally
|
finally
|
||||||
AtomicExchange(FLock, 0);
|
Release;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMycProtectedWriteableMutable<T>.Lock;
|
||||||
|
begin
|
||||||
|
while AtomicExchange(FLock, 1) = 1 do
|
||||||
|
YieldProcessor;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMycProtectedWriteableMutable<T>.Release;
|
||||||
|
begin
|
||||||
|
AtomicExchange(FLock, 0);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TMycProtectedWriteableMutable<T>.SetValue(const Value: T);
|
procedure TMycProtectedWriteableMutable<T>.SetValue(const Value: T);
|
||||||
begin
|
begin
|
||||||
while AtomicExchange(FLock, 1) = 1 do
|
Lock;
|
||||||
YieldProcessor;
|
|
||||||
try
|
try
|
||||||
FValue := Value;
|
FValue := Value;
|
||||||
FChanged.Notify;
|
FChanged.Notify;
|
||||||
finally
|
finally
|
||||||
AtomicExchange(FLock, 0);
|
Release;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
+68
-18
@@ -18,11 +18,6 @@ type
|
|||||||
property Value: T read GetValue;
|
property Value: T read GetValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
IWriteable = interface(IMutable)
|
|
||||||
procedure SetValue(const Value: T);
|
|
||||||
property Value: T read GetValue write SetValue;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{$REGION 'private'}
|
{$REGION 'private'}
|
||||||
strict private
|
strict private
|
||||||
class var
|
class var
|
||||||
@@ -44,13 +39,36 @@ type
|
|||||||
|
|
||||||
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 CreateWriteable(const Init: T): IWriteable; overload; static;
|
|
||||||
class function CreateProtected: IWriteable; overload; static;
|
|
||||||
|
|
||||||
property Value: T read GetValue;
|
property Value: T read GetValue;
|
||||||
property Changed: TSignal read GetChanged;
|
property Changed: TSignal read GetChanged;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TWriteable<T> = record
|
||||||
|
type
|
||||||
|
IWriteable = interface(TMutable<T>.IMutable)
|
||||||
|
procedure SetValue(const Value: T);
|
||||||
|
property Value: T read GetValue write SetValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
private
|
||||||
|
FWriteable: IWriteable;
|
||||||
|
function GetChanged: TSignal; inline;
|
||||||
|
function GetValue: T; inline;
|
||||||
|
procedure SetValue(const Value: T); inline;
|
||||||
|
|
||||||
|
public
|
||||||
|
constructor Create(const AWriteable: IWriteable);
|
||||||
|
|
||||||
|
class function CreateProtected: TWriteable<T>; overload; static;
|
||||||
|
class function CreateWriteable: TWriteable<T>; overload; static;
|
||||||
|
|
||||||
|
class operator Implicit(const A: IWriteable): TWriteable<T>; overload;
|
||||||
|
class operator Implicit(const A: TWriteable<T>): IWriteable; overload;
|
||||||
|
|
||||||
|
property Value: T read GetValue write SetValue;
|
||||||
|
property Changed: TSignal read GetChanged;
|
||||||
|
end;
|
||||||
|
|
||||||
TLazy<T> = record
|
TLazy<T> = record
|
||||||
type
|
type
|
||||||
ILazy = interface
|
ILazy = interface
|
||||||
@@ -109,16 +127,6 @@ begin
|
|||||||
Result := TMycFuncMutable<T>.Create(Changing, Proc);
|
Result := TMycFuncMutable<T>.Create(Changing, Proc);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TMutable<T>.CreateProtected: IWriteable;
|
|
||||||
begin
|
|
||||||
Result := TMycProtectedWriteableMutable<T>.Create(Default(T));
|
|
||||||
end;
|
|
||||||
|
|
||||||
class function TMutable<T>.CreateWriteable(const Init: T): IWriteable;
|
|
||||||
begin
|
|
||||||
Result := TMycWriteableMutable<T>.Create(Init);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TMutable<T>.GetChanged: TSignal;
|
function TMutable<T>.GetChanged: TSignal;
|
||||||
begin
|
begin
|
||||||
Result := FMutable.Changed;
|
Result := FMutable.Changed;
|
||||||
@@ -193,4 +201,46 @@ begin
|
|||||||
Dest.FLazy := FNull;
|
Dest.FLazy := FNull;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TWriteable<T> }
|
||||||
|
|
||||||
|
constructor TWriteable<T>.Create(const AWriteable: IWriteable);
|
||||||
|
begin
|
||||||
|
FWriteable := AWriteable;
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TWriteable<T>.CreateProtected: TWriteable<T>;
|
||||||
|
begin
|
||||||
|
Result := TMycProtectedWriteableMutable<T>.Create(Default(T));
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TWriteable<T>.CreateWriteable: TWriteable<T>;
|
||||||
|
begin
|
||||||
|
Result := TMycWriteableMutable<T>.Create(Default(T));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TWriteable<T>.GetChanged: TSignal;
|
||||||
|
begin
|
||||||
|
Result := FWriteable.Changed;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TWriteable<T>.GetValue: T;
|
||||||
|
begin
|
||||||
|
Result := FWriteable.Value;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TWriteable<T>.SetValue(const Value: T);
|
||||||
|
begin
|
||||||
|
FWriteable.Value := Value;
|
||||||
|
end;
|
||||||
|
|
||||||
|
class operator TWriteable<T>.Implicit(const A: IWriteable): TWriteable<T>;
|
||||||
|
begin
|
||||||
|
Result.Create(A);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class operator TWriteable<T>.Implicit(const A: TWriteable<T>): IWriteable;
|
||||||
|
begin
|
||||||
|
Result := A.FWriteable;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
@@ -54,23 +54,14 @@ type
|
|||||||
function IsHistory: Boolean; virtual; abstract;
|
function IsHistory: Boolean; virtual; abstract;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Represents a factory for creating IDataStream instances.
|
TDataProc<T> = reference to procedure(const Values: TArray<TDataPoint<T>>; const Terminated: TState);
|
||||||
IDataStreamNode<T> = interface
|
|
||||||
['{DA3531F1-158E-4A63-8E5A-34089C537B1B}']
|
|
||||||
function CreateDataStream: IDataStream<T>;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Abstract base class for IDataStreamNode implementations.
|
|
||||||
TDataStreamNode<T> = class(TInterfacedObject, IDataStreamNode<T>)
|
|
||||||
public
|
|
||||||
function CreateDataStream: IDataStream<T>; virtual; abstract;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Interface for an instantiable data server.
|
// Interface for an instantiable data server.
|
||||||
IDataServer<T: record> = interface
|
IDataServer<T: record> = interface
|
||||||
['{1F8E5A9D-E92A-44C1-9F3F-C4B82A6E94B3}']
|
['{1F8E5A9D-E92A-44C1-9F3F-C4B82A6E94B3}']
|
||||||
function CreateStream(const Symbol: String): IDataStream<T>;
|
function CreateStream(const Symbol: String): IDataStream<T>;
|
||||||
procedure ClearCache;
|
procedure ClearCache;
|
||||||
|
function ProcessData(const Symbol: String; const Terminate: TSignal; const Proc: TDataProc<T>): TState;
|
||||||
function EnumerateSymbols: TFuture<TArray<String>>;
|
function EnumerateSymbols: TFuture<TArray<String>>;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -110,6 +101,8 @@ 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 LoadFile(currFile: TAuraDataFile; Terminated: TState; Proc: TDataProc<T>): TState;
|
||||||
|
|
||||||
strict private
|
strict private
|
||||||
class var
|
class var
|
||||||
FLoadGate: TLatch;
|
FLoadGate: TLatch;
|
||||||
@@ -130,6 +123,9 @@ type
|
|||||||
function ParseFileName(const FileName: string): TAuraDataFile; virtual; abstract;
|
function ParseFileName(const FileName: string): TAuraDataFile; virtual; abstract;
|
||||||
function EnumerateSymbols: TFuture<TArray<String>>;
|
function EnumerateSymbols: TFuture<TArray<String>>;
|
||||||
function LoadDataFile(const DataFile: TAuraDataFile): TFuture<TArray<TDataPoint<T>>>;
|
function LoadDataFile(const DataFile: TAuraDataFile): TFuture<TArray<TDataPoint<T>>>;
|
||||||
|
|
||||||
|
function ProcessData(const Symbol: String; const Terminate: TSignal; const Proc: TDataProc<T>): TState;
|
||||||
|
|
||||||
property Path: String read GetPath;
|
property Path: String read GetPath;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -180,13 +176,8 @@ type
|
|||||||
TAuraFileLoader<T: record> = class(TInterfacedObject)
|
TAuraFileLoader<T: record> = class(TInterfacedObject)
|
||||||
type
|
type
|
||||||
TDataProc = reference to procedure(const Values: TArray<TDataPoint<T>>);
|
TDataProc = reference to procedure(const Values: TArray<TDataPoint<T>>);
|
||||||
public
|
|
||||||
class function LoadData(
|
private
|
||||||
DataServer: TAuraDataServer<T>;
|
|
||||||
const Symbol: String;
|
|
||||||
const Terminate: TSignal;
|
|
||||||
const Proc: TDataProc
|
|
||||||
): TState;
|
|
||||||
class procedure LoadFile(
|
class procedure LoadFile(
|
||||||
DataServer: TAuraDataServer<T>;
|
DataServer: TAuraDataServer<T>;
|
||||||
currFile: TAuraDataFile;
|
currFile: TAuraDataFile;
|
||||||
@@ -194,6 +185,14 @@ type
|
|||||||
Done: TLatch;
|
Done: TLatch;
|
||||||
Proc: TDataProc
|
Proc: TDataProc
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public
|
||||||
|
class function LoadData(
|
||||||
|
DataServer: TAuraDataServer<T>;
|
||||||
|
const Symbol: String;
|
||||||
|
const Terminate: TSignal;
|
||||||
|
const Proc: TDataProc
|
||||||
|
): TState;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@@ -409,11 +408,44 @@ begin
|
|||||||
Result := FPath;
|
Result := FPath;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAuraDataServer<T>.ProcessData(const Symbol: String; const Terminate: TSignal; const Proc: TDataProc<T>): TState;
|
||||||
|
begin
|
||||||
|
var capProc := Proc;
|
||||||
|
var terminated := TFlag.CreateObserver(Terminate).State;
|
||||||
|
|
||||||
|
var firstFile := FindFirstFile(Symbol);
|
||||||
|
|
||||||
|
var done := TLatch.CreateLatch(1);
|
||||||
|
Result := done.State;
|
||||||
|
|
||||||
|
TaskManager.CreateTask(firstFile.Done, procedure begin LoadFile(firstFile.Value, terminated, capProc).Subscribe(done); end);
|
||||||
|
end;
|
||||||
|
|
||||||
function TAuraDataServer<T>.LoadDataFile(const DataFile: TAuraDataFile): TFuture<TArray<TDataPoint<T>>>;
|
function TAuraDataServer<T>.LoadDataFile(const DataFile: TAuraDataFile): TFuture<TArray<TDataPoint<T>>>;
|
||||||
begin
|
begin
|
||||||
Result := FCachedFiles.GetOrAdd(DataFile.GetFullFileName);
|
Result := FCachedFiles.GetOrAdd(DataFile.GetFullFileName);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAuraDataServer<T>.LoadFile(currFile: TAuraDataFile; Terminated: TState; Proc: TDataProc<T>): TState;
|
||||||
|
begin
|
||||||
|
if not currFile.IsValid or Terminated.IsSet then
|
||||||
|
exit(TState.Null);
|
||||||
|
|
||||||
|
var done := TLatch.CreateLatch(1);
|
||||||
|
Result := done.State;
|
||||||
|
|
||||||
|
var data := FCachedFiles.GetOrAdd(currFile.GetFullFileName);
|
||||||
|
|
||||||
|
TaskManager.CreateTask(
|
||||||
|
data.Done,
|
||||||
|
procedure
|
||||||
|
begin
|
||||||
|
Proc(data.Value, Terminated);
|
||||||
|
LoadFile(currFile.GetNextFile, Terminated, Proc).Subscribe(done);
|
||||||
|
end
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TAuraFileStream<T> }
|
{ TAuraFileStream<T> }
|
||||||
|
|
||||||
constructor TAuraFileStream<T>.Create(ADataServer: TAuraDataServer<T>; const ASymbol: String);
|
constructor TAuraFileStream<T>.Create(ADataServer: TAuraDataServer<T>; const ASymbol: String);
|
||||||
|
|||||||
Reference in New Issue
Block a user