Memory hole in Data-Join fixed
This commit is contained in:
@@ -31,6 +31,16 @@ type
|
||||
class property Null: IConsumer<T> read FNull;
|
||||
end;
|
||||
|
||||
// A consumer implementation that is owned by a controller.
|
||||
TMycGenericConsumer<T> = class(TMycConsumer<T>)
|
||||
private
|
||||
FProc: TConstFunc<T, TState>;
|
||||
protected
|
||||
function Consume(const Value: T): TState; override; final;
|
||||
public
|
||||
constructor Create(const Controller: IInterface; const AProc: TConstFunc<T, TState>);
|
||||
end;
|
||||
|
||||
TMycProducer<T> = class(TInterfacedObject, IProducer<T>)
|
||||
strict private
|
||||
type
|
||||
@@ -79,18 +89,7 @@ type
|
||||
FNull: IConverter<S, T>;
|
||||
class constructor CreateClass;
|
||||
private
|
||||
type
|
||||
TConsumer = class(TMycConsumer<S>)
|
||||
private
|
||||
FOwner: TMycConverter<S, T>;
|
||||
protected
|
||||
function Consume(const Value: S): TState; override; final;
|
||||
public
|
||||
constructor Create(AOwner: TMycConverter<S, T>);
|
||||
end;
|
||||
|
||||
private
|
||||
FConsumer: TConsumer;
|
||||
FConsumer: TMycGenericConsumer<S>;
|
||||
function GetConsumer: IConsumer<S>;
|
||||
protected
|
||||
// To be implemented by descendants to perform the actual conversion.
|
||||
@@ -162,16 +161,6 @@ type
|
||||
constructor Create(const AFieldName: String);
|
||||
end;
|
||||
|
||||
// A consumer implementation that is owned by a controller.
|
||||
TMycGenericConsumer<T> = class(TMycConsumer<T>)
|
||||
private
|
||||
FProc: TConstFunc<T, TState>;
|
||||
protected
|
||||
function Consume(const Value: T): TState; override;
|
||||
public
|
||||
constructor Create(const Controller: IInterface; const AProc: TConstFunc<T, TState>);
|
||||
end;
|
||||
|
||||
// Endpoint that collects data into a series.
|
||||
TMycDataEndpoint<T> = class(TInterfacedObject, TLazy<TSeries<T>>.ILazy)
|
||||
private
|
||||
@@ -183,9 +172,7 @@ type
|
||||
end;
|
||||
private
|
||||
FConsumer: TMycGenericConsumer<T>;
|
||||
FTag: TTag;
|
||||
FProducer: IProducer<T>;
|
||||
FLookback: Int64;
|
||||
FLookback: Integer;
|
||||
FChanged: TFlag;
|
||||
FLock: TLightweightMREW;
|
||||
FFirst: PItem;
|
||||
@@ -193,9 +180,11 @@ type
|
||||
function GetChanged: TState;
|
||||
function Consume(const Value: T): TState;
|
||||
public
|
||||
constructor Create(const AProducer: TProducer<T>; ALookback: Int64);
|
||||
constructor Create(ALookback: Integer);
|
||||
destructor Destroy; override;
|
||||
function Update(var Value: TSeries<T>): Boolean;
|
||||
|
||||
class function CreateDataEndpoint(Lookback: Integer; out Series: TLazy<TSeries<T>>): IConsumer<T>;
|
||||
end;
|
||||
|
||||
TTickAggregation = class(TMycConverter<TDataPoint<Double>, TDataPoint<TOhlcItem>>)
|
||||
@@ -239,9 +228,7 @@ type
|
||||
TMycDataJoin<T> = class(TInterfacedObject, IProducer<TArray<T>>)
|
||||
private
|
||||
FConsumers: array of record
|
||||
Producer: IProducer<T>;
|
||||
Consumer: TMycGenericConsumer<T>;
|
||||
Tag: TTag;
|
||||
Queue: TQueue<T>;
|
||||
end;
|
||||
|
||||
@@ -249,11 +236,13 @@ type
|
||||
FLock: TSpinLock;
|
||||
FCount: Integer;
|
||||
function Consume(Idx: Integer; const Value: T): TState;
|
||||
function GetConsumers(Idx: Integer): IConsumer<T>;
|
||||
function Link(const Consumer: IConsumer<TArray<T>>): TTag;
|
||||
procedure Unlink(Tag: TTag);
|
||||
public
|
||||
constructor Create(const AProducers: TArray<TProducer<T>>);
|
||||
constructor Create(ACount: Integer);
|
||||
destructor Destroy; override;
|
||||
property Consumers[Idx: Integer]: IConsumer<T> read GetConsumers;
|
||||
end;
|
||||
|
||||
TMycComposedConverter<S, T> = class(TInterfacedObject, IConverter<S, T>)
|
||||
@@ -363,7 +352,7 @@ end;
|
||||
constructor TMycConverter<S, T>.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
FConsumer := TConsumer.Create(Self);
|
||||
FConsumer := TMycGenericConsumer<S>.Create(Self, Consume);
|
||||
end;
|
||||
|
||||
{ TMycConverter<S, T> }
|
||||
@@ -486,19 +475,15 @@ end;
|
||||
|
||||
{ TMycDataEndpoint<T> }
|
||||
|
||||
constructor TMycDataEndpoint<T>.Create(const AProducer: TProducer<T>; ALookback: Int64);
|
||||
constructor TMycDataEndpoint<T>.Create(ALookback: Integer);
|
||||
begin
|
||||
inherited Create;
|
||||
FProducer := AProducer;
|
||||
FLookback := ALookback;
|
||||
|
||||
FConsumer := TMycGenericConsumer<T>.Create(Self, Consume);
|
||||
FTag := FProducer.Link(FConsumer);
|
||||
end;
|
||||
|
||||
destructor TMycDataEndpoint<T>.Destroy;
|
||||
begin
|
||||
FProducer.Unlink(FTag);
|
||||
FConsumer.Free;
|
||||
inherited;
|
||||
end;
|
||||
@@ -524,6 +509,15 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TMycDataEndpoint<T>.CreateDataEndpoint(Lookback: Integer; out Series: TLazy<TSeries<T>>): IConsumer<T>;
|
||||
var
|
||||
endPoint: TMycDataEndpoint<T>;
|
||||
begin
|
||||
endPoint := TMycDataEndpoint<T>.Create(Lookback);
|
||||
Result := endPoint.FConsumer;
|
||||
Series := endPoint;
|
||||
end;
|
||||
|
||||
function TMycDataEndpoint<T>.Update(var Value: TSeries<T>): Boolean;
|
||||
begin
|
||||
FLock.BeginWrite;
|
||||
@@ -801,11 +795,11 @@ end;
|
||||
|
||||
{ TMycDataJoin<T> }
|
||||
|
||||
constructor TMycDataJoin<T>.Create(const AProducers: TArray<TProducer<T>>);
|
||||
constructor TMycDataJoin<T>.Create(ACount: Integer);
|
||||
begin
|
||||
inherited Create;
|
||||
|
||||
SetLength(FConsumers, Length(AProducers));
|
||||
SetLength(FConsumers, ACount);
|
||||
|
||||
FLock := TSpinLock.Create(false);
|
||||
FCount := Length(FConsumers);
|
||||
@@ -822,9 +816,7 @@ begin
|
||||
with FConsumers[i] do
|
||||
begin
|
||||
Queue := TQueue<T>.Create;
|
||||
Producer := AProducers[i];
|
||||
Consumer := TMycGenericConsumer<T>.Create(Self, cFunc(i));
|
||||
Tag := Producer.Link(Consumer);
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -833,7 +825,6 @@ begin
|
||||
for var i := High(FConsumers) downto 0 do
|
||||
with FConsumers[i] do
|
||||
begin
|
||||
Producer.Unlink(FConsumers[i].Tag);
|
||||
Consumer.Free;
|
||||
Queue.Free;
|
||||
end;
|
||||
@@ -884,6 +875,11 @@ begin
|
||||
FContainedProvider.Broadcast(Arr);
|
||||
end;
|
||||
|
||||
function TMycDataJoin<T>.GetConsumers(Idx: Integer): IConsumer<T>;
|
||||
begin
|
||||
Result := FConsumers[Idx].Consumer;
|
||||
end;
|
||||
|
||||
{ TMycGenericAggregator<S, T> }
|
||||
|
||||
constructor TMycGenericAggregator<S, T>.Create(const AFunc: TConstFunc<S, TConverter<S, T>.TBroadcastProc, TState>);
|
||||
@@ -1005,15 +1001,4 @@ begin
|
||||
|
||||
end;
|
||||
|
||||
constructor TMycConverter<S, T>.TConsumer.Create(AOwner: TMycConverter<S, T>);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FOwner := AOwner;
|
||||
end;
|
||||
|
||||
function TMycConverter<S, T>.TConsumer.Consume(const Value: S): TState;
|
||||
begin
|
||||
Result := FOwner.Consume(Value);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user