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; 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;
+65 -57
View File
@@ -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;