Adding Pipes

This commit is contained in:
Michael Schimmel
2025-12-18 13:09:47 +01:00
parent 34b4466a15
commit 8960a5683e
2 changed files with 68 additions and 66 deletions
+3 -9
View File
@@ -200,7 +200,7 @@ type
function GetTotalCount: Int64;
{$endregion}
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 TotalCount: Int64 read GetTotalCount;
end;
@@ -235,13 +235,12 @@ type
function GetDef: IScalarRecordDefinition; inline;
function GetTotalCount: Int64; inline;
function GetItemRef(Idx: Integer): TChunkArray<TScalar.TValue>.PT; inline;
function GetMapping: IKeywordMapping<ISeries>;
public
constructor Create(const ADef: IScalarRecordDefinition);
destructor Destroy; override;
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 Def: IScalarRecordDefinition read GetDef;
@@ -829,7 +828,7 @@ begin
inc(FTotalCount);
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
Assert(Length(Items) = FDef.Count, 'Array does not fit series definition');
@@ -864,11 +863,6 @@ begin
Result := FArray.ItemRef[(FArray.Count - len) - (Idx * len)];
end;
function TScalarRecordSeries.GetMapping: IKeywordMapping<ISeries>;
begin
Result := Self;
end;
function TScalarRecordSeries.GetTotalCount: Int64;
begin
Result := FTotalCount;
+36 -28
View File
@@ -77,11 +77,12 @@ type
// Acts as IStream (Producer) for downstream consumers and manages internal inputs.
TPipeStream = class(TInterfacedObject, IStream)
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
FConfig: TPipeConfig;
FSources: TArray<TPipeSource>;
FObservers: TMycNotifyList<IStreamObserver>;
FSourceSeries: TArray<ISeries>;
FSeries: IWriteableScalarRecordSeries;
// Barrier State
@@ -90,17 +91,21 @@ type
// Execution Logic
// The compiled lambda function representing (fn [inputs...] ...)
FLambda: TProc;
FLambdaArgs: TArray<ISeries>;
procedure CheckBarrierAndFire(CurrentCycle: Int64);
function GetSeries: IScalarRecordSeries;
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;
// Injected into lambda scope as "emit"
procedure Emit(const Value: IScalarRecord);
procedure Emit(const Data: array of TScalar.TValue);
// IStream Implementation
function Subscribe(const Observer: IStreamObserver): TSubscriptionTag;
@@ -138,20 +143,25 @@ end;
{ TPipeStream }
constructor TPipeStream.Create(const AConfig: TPipeConfig; const ASources: TArray<IStream>; const ALambda: TProc);
var
fields: TArray<TScalarRecordField>;
constructor TPipeStream.Create(
const AConfig: TPipeConfig;
const ADef: IScalarRecordDefinition;
const ASources: TArray<IStream>;
const ALambda: TProc
);
begin
inherited Create;
FConfig := AConfig;
FLambda := ALambda;
FLastFiredCycleID := -1;
Assert(Length(AConfig) = Length(ASources));
SetLength(FSources, Length(ASources));
FSeries := TScalarRecordSeries.Create(ADef);
// Construct record series definition from source config
SetLength(FSources, Length(ASources));
SetLength(FSourceSeries, Length(ASources));
var n := 0;
for var i := 0 to High(AConfig) do
begin
@@ -160,22 +170,14 @@ begin
inc(n, Length(AConfig[i]));
end;
SetLength(FLambdaArgs, n);
SetLength(FSourceSeries, n);
n := 0;
for var i := 0 to High(AConfig) do
begin
for var j := 0 to High(AConfig[i]) do
begin
fields[n] := AConfig[i][j];
FLambdaArgs[n] := ASources[i].Series[j].Value;
FSourceSeries[n] := ASources[i].Series.Fields[AConfig[i][j].Key];
inc(n);
end;
end;
FSeries := TScalarRecordSeries.Create(TScalarRecord.TRegistry.Intern(fields));
end;
destructor TPipeStream.Destroy;
@@ -211,6 +213,8 @@ end;
procedure TPipeStream.CheckBarrierAndFire(CurrentCycle: Int64);
begin
FObservers.Lock;
try
// Barrier Check
for var src in FSources do
begin
@@ -229,19 +233,26 @@ begin
if Assigned(FLambda) then
begin
try
FLambda(FLambdaArgs);
FLambda(FSourceSeries, Emit);
except
// Error handling strategy: Propagate/Crash for now.
raise;
end;
end;
finally
FObservers.Release;
end;
end;
procedure TPipeStream.Emit(const Value: IScalarRecord);
procedure TPipeStream.Emit(const Data: array of TScalar.TValue);
begin
FObservers.Lock;
try
FSeries.Add(Value);
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(
@@ -251,9 +262,6 @@ begin
Result := True;
end
);
finally
FObservers.Release;
end;
end;
function TPipeStream.GetSeries: IScalarRecordSeries;