Adding Pipes
This commit is contained in:
@@ -200,7 +200,7 @@ type
|
|||||||
function GetTotalCount: Int64;
|
function GetTotalCount: Int64;
|
||||||
{$endregion}
|
{$endregion}
|
||||||
procedure Add(const Item: IKeywordMapping<TScalar>; Lookback: Int64 = -1); overload;
|
procedure Add(const Item: IKeywordMapping<TScalar>; Lookback: Int64 = -1); overload;
|
||||||
procedure Add(const Items: TArray<TScalar.TValue>; Lookback: Int64 = -1); overload;
|
procedure Add(const Items: array of TScalar.TValue; Lookback: Int64 = -1); overload;
|
||||||
property RecordCount: Int64 read GetRecordCount;
|
property RecordCount: Int64 read GetRecordCount;
|
||||||
property TotalCount: Int64 read GetTotalCount;
|
property TotalCount: Int64 read GetTotalCount;
|
||||||
end;
|
end;
|
||||||
@@ -235,13 +235,12 @@ type
|
|||||||
function GetDef: IScalarRecordDefinition; inline;
|
function GetDef: IScalarRecordDefinition; inline;
|
||||||
function GetTotalCount: Int64; inline;
|
function GetTotalCount: Int64; inline;
|
||||||
function GetItemRef(Idx: Integer): TChunkArray<TScalar.TValue>.PT; inline;
|
function GetItemRef(Idx: Integer): TChunkArray<TScalar.TValue>.PT; inline;
|
||||||
function GetMapping: IKeywordMapping<ISeries>;
|
|
||||||
public
|
public
|
||||||
constructor Create(const ADef: IScalarRecordDefinition);
|
constructor Create(const ADef: IScalarRecordDefinition);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
procedure Add(const Item: IKeywordMapping<TScalar>; Lookback: Int64 = -1); overload;
|
procedure Add(const Item: IKeywordMapping<TScalar>; Lookback: Int64 = -1); overload;
|
||||||
procedure Add(const Items: TArray<TScalar.TValue>; Lookback: Int64 = -1); overload;
|
procedure Add(const Items: array of TScalar.TValue; Lookback: Int64 = -1); overload;
|
||||||
|
|
||||||
property RecordCount: Int64 read GetRecordCount;
|
property RecordCount: Int64 read GetRecordCount;
|
||||||
property Def: IScalarRecordDefinition read GetDef;
|
property Def: IScalarRecordDefinition read GetDef;
|
||||||
@@ -829,7 +828,7 @@ begin
|
|||||||
inc(FTotalCount);
|
inc(FTotalCount);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TScalarRecordSeries.Add(const Items: TArray<TScalar.TValue>; Lookback: Int64 = -1);
|
procedure TScalarRecordSeries.Add(const Items: array of TScalar.TValue; Lookback: Int64 = -1);
|
||||||
begin
|
begin
|
||||||
Assert(Length(Items) = FDef.Count, 'Array does not fit series definition');
|
Assert(Length(Items) = FDef.Count, 'Array does not fit series definition');
|
||||||
|
|
||||||
@@ -864,11 +863,6 @@ begin
|
|||||||
Result := FArray.ItemRef[(FArray.Count - len) - (Idx * len)];
|
Result := FArray.ItemRef[(FArray.Count - len) - (Idx * len)];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TScalarRecordSeries.GetMapping: IKeywordMapping<ISeries>;
|
|
||||||
begin
|
|
||||||
Result := Self;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TScalarRecordSeries.GetTotalCount: Int64;
|
function TScalarRecordSeries.GetTotalCount: Int64;
|
||||||
begin
|
begin
|
||||||
Result := FTotalCount;
|
Result := FTotalCount;
|
||||||
|
|||||||
@@ -77,11 +77,12 @@ type
|
|||||||
// Acts as IStream (Producer) for downstream consumers and manages internal inputs.
|
// Acts as IStream (Producer) for downstream consumers and manages internal inputs.
|
||||||
TPipeStream = class(TInterfacedObject, IStream)
|
TPipeStream = class(TInterfacedObject, IStream)
|
||||||
type
|
type
|
||||||
TProc = reference to procedure(const Series: TArray<ISeries>);
|
TEmitProc = reference to procedure(const Data: array of TScalar.TValue);
|
||||||
|
TProc = reference to procedure(const Sources: TArray<ISeries>; const Emit: TEmitProc);
|
||||||
private
|
private
|
||||||
FConfig: TPipeConfig;
|
|
||||||
FSources: TArray<TPipeSource>;
|
FSources: TArray<TPipeSource>;
|
||||||
FObservers: TMycNotifyList<IStreamObserver>;
|
FObservers: TMycNotifyList<IStreamObserver>;
|
||||||
|
FSourceSeries: TArray<ISeries>;
|
||||||
FSeries: IWriteableScalarRecordSeries;
|
FSeries: IWriteableScalarRecordSeries;
|
||||||
|
|
||||||
// Barrier State
|
// Barrier State
|
||||||
@@ -90,17 +91,21 @@ type
|
|||||||
// Execution Logic
|
// Execution Logic
|
||||||
// The compiled lambda function representing (fn [inputs...] ...)
|
// The compiled lambda function representing (fn [inputs...] ...)
|
||||||
FLambda: TProc;
|
FLambda: TProc;
|
||||||
FLambdaArgs: TArray<ISeries>;
|
|
||||||
|
|
||||||
procedure CheckBarrierAndFire(CurrentCycle: Int64);
|
procedure CheckBarrierAndFire(CurrentCycle: Int64);
|
||||||
function GetSeries: IScalarRecordSeries;
|
function GetSeries: IScalarRecordSeries;
|
||||||
|
|
||||||
public
|
public
|
||||||
constructor Create(const AConfig: TPipeConfig; const ASources: TArray<IStream>; const ALambda: TProc);
|
constructor Create(
|
||||||
|
const AConfig: TPipeConfig;
|
||||||
|
const ADef: IScalarRecordDefinition;
|
||||||
|
const ASources: TArray<IStream>;
|
||||||
|
const ALambda: TProc
|
||||||
|
);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
// Injected into lambda scope as "emit"
|
// Injected into lambda scope as "emit"
|
||||||
procedure Emit(const Value: IScalarRecord);
|
procedure Emit(const Data: array of TScalar.TValue);
|
||||||
|
|
||||||
// IStream Implementation
|
// IStream Implementation
|
||||||
function Subscribe(const Observer: IStreamObserver): TSubscriptionTag;
|
function Subscribe(const Observer: IStreamObserver): TSubscriptionTag;
|
||||||
@@ -138,20 +143,25 @@ end;
|
|||||||
|
|
||||||
{ TPipeStream }
|
{ TPipeStream }
|
||||||
|
|
||||||
constructor TPipeStream.Create(const AConfig: TPipeConfig; const ASources: TArray<IStream>; const ALambda: TProc);
|
constructor TPipeStream.Create(
|
||||||
var
|
const AConfig: TPipeConfig;
|
||||||
fields: TArray<TScalarRecordField>;
|
const ADef: IScalarRecordDefinition;
|
||||||
|
const ASources: TArray<IStream>;
|
||||||
|
const ALambda: TProc
|
||||||
|
);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
FConfig := AConfig;
|
|
||||||
FLambda := ALambda;
|
FLambda := ALambda;
|
||||||
FLastFiredCycleID := -1;
|
FLastFiredCycleID := -1;
|
||||||
|
|
||||||
Assert(Length(AConfig) = Length(ASources));
|
Assert(Length(AConfig) = Length(ASources));
|
||||||
|
|
||||||
SetLength(FSources, Length(ASources));
|
FSeries := TScalarRecordSeries.Create(ADef);
|
||||||
|
|
||||||
// Construct record series definition from source config
|
// Construct record series definition from source config
|
||||||
|
SetLength(FSources, Length(ASources));
|
||||||
|
SetLength(FSourceSeries, Length(ASources));
|
||||||
|
|
||||||
var n := 0;
|
var n := 0;
|
||||||
for var i := 0 to High(AConfig) do
|
for var i := 0 to High(AConfig) do
|
||||||
begin
|
begin
|
||||||
@@ -160,22 +170,14 @@ begin
|
|||||||
inc(n, Length(AConfig[i]));
|
inc(n, Length(AConfig[i]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
SetLength(FLambdaArgs, n);
|
SetLength(FSourceSeries, n);
|
||||||
|
|
||||||
n := 0;
|
n := 0;
|
||||||
for var i := 0 to High(AConfig) do
|
for var i := 0 to High(AConfig) do
|
||||||
begin
|
|
||||||
for var j := 0 to High(AConfig[i]) do
|
for var j := 0 to High(AConfig[i]) do
|
||||||
begin
|
begin
|
||||||
fields[n] := AConfig[i][j];
|
FSourceSeries[n] := ASources[i].Series.Fields[AConfig[i][j].Key];
|
||||||
|
|
||||||
FLambdaArgs[n] := ASources[i].Series[j].Value;
|
|
||||||
|
|
||||||
inc(n);
|
inc(n);
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
|
|
||||||
FSeries := TScalarRecordSeries.Create(TScalarRecord.TRegistry.Intern(fields));
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TPipeStream.Destroy;
|
destructor TPipeStream.Destroy;
|
||||||
@@ -210,52 +212,58 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPipeStream.CheckBarrierAndFire(CurrentCycle: Int64);
|
procedure TPipeStream.CheckBarrierAndFire(CurrentCycle: Int64);
|
||||||
begin
|
|
||||||
// Barrier Check
|
|
||||||
for var src in FSources do
|
|
||||||
begin
|
|
||||||
if src.LastSeenCycle < CurrentCycle then
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// --- Barrier Open ---
|
|
||||||
|
|
||||||
if FLastFiredCycleID >= CurrentCycle then
|
|
||||||
exit;
|
|
||||||
|
|
||||||
FLastFiredCycleID := CurrentCycle;
|
|
||||||
|
|
||||||
// Execute Lambda
|
|
||||||
if Assigned(FLambda) then
|
|
||||||
begin
|
|
||||||
try
|
|
||||||
FLambda(FLambdaArgs);
|
|
||||||
except
|
|
||||||
// Error handling strategy: Propagate/Crash for now.
|
|
||||||
raise;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TPipeStream.Emit(const Value: IScalarRecord);
|
|
||||||
begin
|
begin
|
||||||
FObservers.Lock;
|
FObservers.Lock;
|
||||||
try
|
try
|
||||||
FSeries.Add(Value);
|
// Barrier Check
|
||||||
var signal := TStreamSignal.Create(skData, FLastFiredCycleID);
|
for var src in FSources do
|
||||||
|
begin
|
||||||
|
if src.LastSeenCycle < CurrentCycle then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
FObservers.Notify(
|
// --- Barrier Open ---
|
||||||
function(const Obs: IStreamObserver): Boolean
|
|
||||||
begin
|
if FLastFiredCycleID >= CurrentCycle then
|
||||||
Obs.OnSignal(signal);
|
exit;
|
||||||
Result := True;
|
|
||||||
end
|
FLastFiredCycleID := CurrentCycle;
|
||||||
);
|
|
||||||
|
// Execute Lambda
|
||||||
|
if Assigned(FLambda) then
|
||||||
|
begin
|
||||||
|
try
|
||||||
|
FLambda(FSourceSeries, Emit);
|
||||||
|
except
|
||||||
|
// Error handling strategy: Propagate/Crash for now.
|
||||||
|
raise;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
finally
|
finally
|
||||||
FObservers.Release;
|
FObservers.Release;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPipeStream.Emit(const Data: array of TScalar.TValue);
|
||||||
|
begin
|
||||||
|
Assert(Length(Data) = FSeries.Def.Count);
|
||||||
|
|
||||||
|
// Emit has to be called from the Lambda, which is called in CheckBarrierAndFire!
|
||||||
|
Assert(FObservers.IsLocked);
|
||||||
|
|
||||||
|
FSeries.Add(Data);
|
||||||
|
|
||||||
|
var signal := TStreamSignal.Create(skData, FLastFiredCycleID);
|
||||||
|
|
||||||
|
FObservers.Notify(
|
||||||
|
function(const Obs: IStreamObserver): Boolean
|
||||||
|
begin
|
||||||
|
Obs.OnSignal(signal);
|
||||||
|
Result := True;
|
||||||
|
end
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
function TPipeStream.GetSeries: IScalarRecordSeries;
|
function TPipeStream.GetSeries: IScalarRecordSeries;
|
||||||
begin
|
begin
|
||||||
Result := FSeries;
|
Result := FSeries;
|
||||||
|
|||||||
Reference in New Issue
Block a user