Refactoring IState - ISignal

This commit is contained in:
Michael Schimmel
2025-06-24 09:24:37 +02:00
parent a3da63ad6a
commit 6ea0f94e36
11 changed files with 120 additions and 118 deletions
+21 -24
View File
@@ -93,7 +93,7 @@ begin
FSymbolsValid := FSymbolsValid :=
TFMXValidationState.Create( TFMXValidationState.Create(
SymbolsComboBox, SymbolsComboBox,
FSymbols.Done, FSymbols.Done.Signal,
procedure procedure
begin begin
SymbolsComboBox.BeginUpdate; SymbolsComboBox.BeginUpdate;
@@ -143,14 +143,11 @@ end;
procedure TForm1.RandomButtonClick(Sender: TObject); procedure TForm1.RandomButtonClick(Sender: TObject);
begin begin
var tst: TFlag := TFlag.CreateObserver( TSignal.Null );
var rnd: TRndItem; var rnd: TRndItem;
var ass := FSymbols.WaitFor; var ass := FSymbols.WaitFor;
rnd.Stream := FServer.CreateStream(ass[Random(Length(FSymbols.WaitFor))]); rnd.Stream := FServer.CreateStream(ass[Random(Length(FSymbols.WaitFor))]);
rnd.Data := TDataStreamProvider.Create<TAskBidItem>(3000, 100, rnd.Stream); rnd.Data := TDataStreamProvider.Create<TAskBidItem>(3000, 1000, rnd.Stream);
rnd.Labl := TLabel.Create(Self); rnd.Labl := TLabel.Create(Self);
rnd.Labl.Parent := FlowLayout; rnd.Labl.Parent := FlowLayout;
@@ -163,26 +160,26 @@ begin
var Proc := var Proc :=
procedure(idx: Integer) procedure(idx: Integer)
begin begin
TFMXValidationState.Create( TFMXValidationState.Create(
FRandom[idx].Labl, FRandom[idx].Labl,
FRandom[idx].Stream.HasData, FRandom[idx].Stream.HasData,
procedure procedure
begin
var data := FRandom[idx].Data.Value;
if data.Count > 0 then
begin begin
var data := FRandom[idx].Data.Value; var dp := data[0];
if data.Count > 0 then FRandom[idx].Labl.Text :=
begin FRandom[idx].Stream.Symbol
var dp := data[0]; + ' '
FRandom[idx].Labl.Text := + dp.Time.ToString
FRandom[idx].Stream.Symbol + ' '
+ ' ' + data.TotalCount.ToString
+ dp.Time.ToString + ' '
+ ' ' + dp.Data.Ask.ToString;
+ data.TotalCount.ToString end;
+ ' ' end
+ dp.Data.Ask.ToString; );
end;
end
);
end; end;
Proc(FRandom.Count - 1); Proc(FRandom.Count - 1);
end; end;
+1
View File
@@ -154,6 +154,7 @@ constructor TMycLazyBase<T>.Create(const AChanged: TSignal);
begin begin
inherited Create; inherited Create;
FChanged := TFlag.CreateFlag; FChanged := TFlag.CreateFlag;
FChanged.Notify;
FChangeState := AChanged.Subscribe(FChanged); FChangeState := AChanged.Subscribe(FChanged);
end; end;
+27 -13
View File
@@ -8,30 +8,29 @@ uses
Myc.Signals; Myc.Signals;
type type
// TMycNullSignal implements a "null object" pattern for IMycState. // TMycNullSignal implements a "null object" pattern for ISignal.
// This state is always considered "set".
TMycNullSignal = class(TInterfacedObject, TSignal.ISignal) TMycNullSignal = class(TInterfacedObject, TSignal.ISignal)
public public
function Subscribe(Subscriber: TSignal.ISubscriber): Pointer; function Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
procedure Unsubscribe(Tag: Pointer); procedure Unsubscribe(Tag: Pointer);
end; end;
// TMycNullState implements a "null object" pattern for IMycState. // TMycNullState implements a "null object" pattern for IState.
// This state is always considered "set". // This state is always considered "set".
TMycNullState = class(TInterfacedObject, TSignal.ISignal, TState.IState) TMycNullState = class(TInterfacedObject, TSignal.ISignal, TState.IState)
protected private
// TState.IState function GetSignal: TSignal;
function GetIsSet: Boolean; function GetIsSet: Boolean;
public public
function Subscribe(Subscriber: TSignal.ISubscriber): Pointer; function Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
procedure Unsubscribe(Tag: Pointer); procedure Unsubscribe(Tag: Pointer);
property Signal: TSignal read GetSignal;
end; end;
// A state that acts as an event. It's state ist always set and it will always Trigger it's subscribers, if it gets notified by itself. // A state that acts as an event. It's state ist always set and it will always Trigger it's subscribers, if it gets notified by itself.
TMycEvent = class(TInterfacedObject, TSignal.ISubscriber, TSignal.ISignal, TEvent.IEvent) TMycEvent = class(TInterfacedObject, TSignal.ISubscriber, TSignal.ISignal, TEvent.IEvent)
strict private strict private
FSubscribers: TMycNotifyList<TSignal.ISubscriber>; FSubscribers: TMycNotifyList<TSignal.ISubscriber>;
protected
function GetSignal: TSignal; function GetSignal: TSignal;
function GetIsSet: Boolean; function GetIsSet: Boolean;
public public
@@ -69,7 +68,7 @@ type
[volatile] [volatile]
FCount: Integer; // The internal countdown value for the latch. FCount: Integer; // The internal countdown value for the latch.
function GetState: TState; // Implementation for TLatch.ILatch.GetState and IFlag.GetState. function GetState: TState; // Implementation for TLatch.ILatch.GetState and IFlag.GetState.
protected function GetSignal: TSignal;
function GetIsSet: Boolean; function GetIsSet: Boolean;
public public
// Creates the latch with an initial count. // Creates the latch with an initial count.
@@ -103,11 +102,11 @@ type
[volatile] [volatile]
FFlag: Boolean; // Internal state: true if dirty/set, false if clean/reset. FFlag: Boolean; // Internal state: true if dirty/set, false if clean/reset.
function GetState: TState; function GetState: TState;
protected function GetSignal: TSignal;
function GetIsSet: Boolean; function GetIsSet: Boolean;
public public
// Creates a new dirty flag, initially set to dirty (true). // Creates a new dirty flag, initially set to dirty (true).
constructor Create; constructor Create(AInit: Boolean);
destructor Destroy; override; destructor Destroy; override;
// Factory method to create a new TMycFlag instance. // Factory method to create a new TMycFlag instance.
@@ -166,6 +165,11 @@ begin
Result := true; // Null state is always set. Result := true; // Null state is always set.
end; end;
function TMycNullState.GetSignal: TSignal;
begin
Result := Self;
end;
function TMycNullState.Subscribe(Subscriber: TSignal.ISubscriber): Pointer; function TMycNullState.Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
begin begin
// Since the state is always set, notify the subscriber immediately. // Since the state is always set, notify the subscriber immediately.
@@ -327,6 +331,11 @@ begin
Result := FCount <= 0; Result := FCount <= 0;
end; end;
function TMycLatch.GetSignal: TSignal;
begin
Result := Self;
end;
function TMycLatch.GetState: TState; function TMycLatch.GetState: TState;
begin begin
// TMycLatch itself implements TState.IState. // TMycLatch itself implements TState.IState.
@@ -392,17 +401,17 @@ end;
{ TMycFlag } { TMycFlag }
constructor TMycFlag.Create; constructor TMycFlag.Create(AInit: Boolean);
begin begin
inherited Create; inherited Create;
FFlag := false; FFlag := AInit;
FSubscribers.Create; FSubscribers.Create;
end; end;
class function TMycFlag.CreateDirty: TFlag.IFlag; class function TMycFlag.CreateDirty: TFlag.IFlag;
begin begin
// Factory method to create a new TMycFlag instance. // Factory method to create a new TMycFlag instance.
Result := TMycFlag.Create; Result := TMycFlag.Create( true );
end; end;
destructor TMycFlag.Destroy; destructor TMycFlag.Destroy;
@@ -423,6 +432,11 @@ begin
Result := FFlag; Result := FFlag;
end; end;
function TMycFlag.GetSignal: TSignal;
begin
Result := Self;
end;
function TMycFlag.GetState: TState; function TMycFlag.GetState: TState;
begin begin
// TMycFlag itself implements TState.IState. // TMycFlag itself implements TState.IState.
@@ -497,7 +511,7 @@ end;
constructor TMycObserverFlag.Create(const ASignal: TSignal.ISignal); constructor TMycObserverFlag.Create(const ASignal: TSignal.ISignal);
begin begin
inherited Create; inherited Create( false );
FSignal := ASignal; FSignal := ASignal;
end; end;
+2 -2
View File
@@ -197,7 +197,7 @@ begin
else else
begin begin
// The job will run when Gate notifies the subscriber returned by Run. // The job will run when Gate notifies the subscriber returned by Run.
Result := Gate.Subscribe(Run(Proc)); Result := Gate.Signal.Subscribe(Run(Proc));
end; end;
end; end;
@@ -361,7 +361,7 @@ begin
lock := TSemaphore.Create(nil, 0, 1, ''); lock := TSemaphore.Create(nil, 0, 1, '');
try try
{var subscription :=} {var subscription :=}
State.Subscribe(TMycTaskWait.Create(lock)); State.Signal.Subscribe(TMycTaskWait.Create(lock));
lock.Acquire; lock.Acquire;
finally finally
FWaitSemaphores.Push(lock); FWaitSemaphores.Push(lock);
+4 -6
View File
@@ -93,9 +93,8 @@ uses
constructor TMutable<T>.Create(const AMutable: IMutable); constructor TMutable<T>.Create(const AMutable: IMutable);
begin begin
FMutable := AMutable; if Assigned(AMutable) then
if not Assigned(FMutable) then FMutable := AMutable;
FMutable := FNull;
end; end;
class constructor TMutable<T>.CreateClass; class constructor TMutable<T>.CreateClass;
@@ -142,9 +141,8 @@ end;
constructor TLazy<T>.Create(const ALazy: ILazy); constructor TLazy<T>.Create(const ALazy: ILazy);
begin begin
FLazy := ALazy; if Assigned(ALazy) then
if not Assigned(FLazy) then FLazy := ALazy;
FLazy := FNull;
end; end;
class function TLazy<T>.Construct(const Changing: TSignal.ISignal; const Proc: TFunc<T>): TLazy<T>; class function TLazy<T>.Construct(const Changing: TSignal.ISignal; const Proc: TFunc<T>): TLazy<T>;
+34 -44
View File
@@ -25,7 +25,6 @@ type
FTag: TSubscriptionTag; FTag: TSubscriptionTag;
constructor Create(const ASignal: ISignal; ATag: TSubscriptionTag); constructor Create(const ASignal: ISignal; ATag: TSubscriptionTag);
public public
class operator Initialize(out Dest: TSubscription);
// Unsubscribes from the associated signal // Unsubscribes from the associated signal
procedure Unsubscribe; procedure Unsubscribe;
end; end;
@@ -52,12 +51,14 @@ type
TState = record TState = record
type type
IState = interface(TSignal.ISignal) IState = interface
{$REGION 'property access'} {$REGION 'property access'}
function GetIsSet: Boolean; function GetIsSet: Boolean;
function GetSignal: TSignal;
{$ENDREGION} {$ENDREGION}
// IsSet is true if the TState has been reached or the condition is met. // IsSet is true if the TState has been reached or the condition is met.
property IsSet: Boolean read GetIsSet; property IsSet: Boolean read GetIsSet;
property Signal: TSignal read GetSignal;
end; end;
{$REGION 'private'} {$REGION 'private'}
@@ -69,7 +70,7 @@ type
private private
FState: IState; FState: IState;
function GetIsSet: Boolean; inline; function GetIsSet: Boolean; inline;
function GetAsSignal: TSignal; inline; function GetSignal: TSignal; inline;
{$ENDREGION} {$ENDREGION}
public public
constructor Create(const AState: IState); constructor Create(const AState: IState);
@@ -80,15 +81,12 @@ type
class function All(const States: TArray<TState>): TState; static; class function All(const States: TArray<TState>): TState; static;
class function Any(const States: TArray<TState>): TState; static; class function Any(const States: TArray<TState>): TState; static;
class property Null: IState read FNull;
function Subscribe(Subscriber: TSignal.ISubscriber): TSignal.TSubscription; inline; function Subscribe(Subscriber: TSignal.ISubscriber): TSignal.TSubscription; inline;
property IsSet: Boolean read GetIsSet; class property Null: IState read FNull;
// Explicitly cast a state to a signal. This is dangerous, use with care! property IsSet: Boolean read GetIsSet;
// States only notify, when they change. This behaviour is obscured by treating it like a signal. property Signal: TSignal read GetSignal;
property AsSignal: TSignal read GetAsSignal;
end; end;
// An event is a stateless signal that forwards all notifications to the subscribers. // An event is a stateless signal that forwards all notifications to the subscribers.
@@ -195,7 +193,7 @@ type
class operator Implicit(const A: IFlag): TFlag; overload; class operator Implicit(const A: IFlag): TFlag; overload;
class operator Implicit(const A: TFlag): IFlag; overload; class operator Implicit(const A: TFlag): IFlag; overload;
class function CreateFlag: TFlag; static; class function CreateFlag(Init: Boolean = false): TFlag; static;
class function CreateObserver(const Signal: TSignal): TFlag; static; class function CreateObserver(const Signal: TSignal): TFlag; static;
class property Null: IFlag read FNull; class property Null: IFlag read FNull;
@@ -222,24 +220,20 @@ end;
procedure TSignal.TSubscription.Unsubscribe; procedure TSignal.TSubscription.Unsubscribe;
begin begin
FSignal.Unsubscribe(FTag); if Assigned(FSignal) then
FSignal := TSignal.Null; begin
FSignal.Unsubscribe(FTag);
FSignal := TSignal.Null;
end;
FTag := nil; FTag := nil;
end; end;
class operator TSignal.TSubscription.Initialize(out Dest: TSubscription);
begin
Dest.FSignal := TSignal.Null;
Dest.FTag := nil;
end;
{ TState } { TState }
constructor TState.Create(const AState: IState); constructor TState.Create(const AState: IState);
begin begin
FState := AState; if Assigned(AState) then
if not Assigned(FState) then FState := AState;
FState := FNull;
end; end;
class constructor TState.ClassCreate; class constructor TState.ClassCreate;
@@ -253,8 +247,8 @@ var
Latch: TLatch.ILatch; Latch: TLatch.ILatch;
begin begin
Latch := TLatch.CreateLatch(Length(States)); Latch := TLatch.CreateLatch(Length(States));
for var i := 0 to High(States) do for var state in States do
States[i].Subscribe(Latch); state.Signal.Subscribe(Latch);
Result := Latch.State; Result := Latch.State;
end; end;
@@ -269,15 +263,15 @@ begin
else else
begin begin
Latch := TLatch.CreateLatch(1); Latch := TLatch.CreateLatch(1);
for var i := 0 to High(States) do for var state in States do
States[i].Subscribe(Latch); state.Signal.Subscribe(Latch);
Result := Latch.State; Result := Latch.State;
end; end;
end; end;
function TState.GetAsSignal: TSignal; function TState.GetSignal: TSignal;
begin begin
Result := FState; Result := FState.Signal;
end; end;
function TState.GetIsSet: Boolean; function TState.GetIsSet: Boolean;
@@ -287,7 +281,7 @@ end;
function TState.Subscribe(Subscriber: TSignal.ISubscriber): TSignal.TSubscription; function TState.Subscribe(Subscriber: TSignal.ISubscriber): TSignal.TSubscription;
begin begin
Result := TSignal.TSubscription.Create(FState, FState.Subscribe(Subscriber)); Result := Signal.Subscribe(Subscriber);
end; end;
class operator TState.Implicit(const A: TState): IState; class operator TState.Implicit(const A: TState): IState;
@@ -309,9 +303,8 @@ end;
constructor TEvent.Create(const AEvent: IEvent); constructor TEvent.Create(const AEvent: IEvent);
begin begin
FEvent := AEvent; if Assigned(AEvent) then
if not Assigned(FEvent) then FEvent := AEvent;
FEvent := FNull;
end; end;
class constructor TEvent.ClassCreate; class constructor TEvent.ClassCreate;
@@ -363,14 +356,13 @@ end;
constructor TFlag.Create(const AFlag: IFlag); constructor TFlag.Create(const AFlag: IFlag);
begin begin
FFlag := AFlag; if Assigned(AFlag) then
if not Assigned(FFlag) then FFlag := AFlag;
FFlag := FNull;
end; end;
class function TFlag.CreateFlag: TFlag; class function TFlag.CreateFlag(Init: Boolean = false): TFlag;
begin begin
Result := TMycFlag.Create; Result := TMycFlag.Create( Init );
end; end;
class function TFlag.CreateObserver(const Signal: TSignal): TFlag; class function TFlag.CreateObserver(const Signal: TSignal): TFlag;
@@ -419,9 +411,8 @@ end;
constructor TLatch.Create(const ALatch: TLatch.ILatch); constructor TLatch.Create(const ALatch: TLatch.ILatch);
begin begin
FLatch := ALatch; if Assigned(ALatch) then
if not Assigned(FLatch) then FLatch := ALatch;
FLatch := FNull;
end; end;
class function TLatch.CreateLatch(Count: Integer): ILatch; class function TLatch.CreateLatch(Count: Integer): ILatch;
@@ -445,7 +436,7 @@ begin
until AtomicCmpExchange(FQueueLock, 1, 0) = 0; until AtomicCmpExchange(FQueueLock, 1, 0) = 0;
try try
Gate.State.Subscribe(Latch); Gate.State.Signal.Subscribe(Latch);
Gate := Latch; Gate := Latch;
Result := Latch.State; Result := Latch.State;
finally finally
@@ -466,7 +457,7 @@ begin
until AtomicCmpExchange(FQueueLock, 1, 0) = 0; until AtomicCmpExchange(FQueueLock, 1, 0) = 0;
try try
FLatch.State.Subscribe(Latch); FLatch.State.Signal.Subscribe(Latch);
FLatch := Latch; FLatch := Latch;
Result := FLatch.State; Result := FLatch.State;
finally finally
@@ -508,9 +499,8 @@ end;
constructor TSignal.Create(const ASignal: ISignal); constructor TSignal.Create(const ASignal: ISignal);
begin begin
FSignal := ASignal; if Assigned(FSignal) then
if not Assigned(FSignal) then FSignal := ASignal;
FSignal := FNull;
end; end;
function TSignal.Subscribe(Subscriber: ISubscriber): TSubscription; function TSignal.Subscribe(Subscriber: ISubscriber): TSubscription;
+1 -1
View File
@@ -74,7 +74,7 @@ end;
function TMycTaskManagerMock.CreateTask(const Gate: TState; const Proc: TProc): TSignal.TSubscription; function TMycTaskManagerMock.CreateTask(const Gate: TState; const Proc: TProc): TSignal.TSubscription;
begin begin
Result := Gate.Subscribe(TMycExecMock.Create(Proc)); Result := Gate.Signal.Subscribe(TMycExecMock.Create(Proc));
end; end;
procedure TMycTaskManagerMock.WaitFor(State: TState.IState); procedure TMycTaskManagerMock.WaitFor(State: TState.IState);
+11 -11
View File
@@ -150,7 +150,7 @@ var
begin begin
sourceDirty := TFlag.CreateFlag; sourceDirty := TFlag.CreateFlag;
sourceDirty.Reset; sourceDirty.Reset;
funcLazy := TMycFuncLazy<Integer>.Create(sourceDirty.State, function: Integer begin Result := 10; end); funcLazy := TMycFuncLazy<Integer>.Create(sourceDirty.State.Signal, function: Integer begin Result := 10; end);
Assert.IsNotNull(funcLazy, 'TMycFuncLazy<Integer> instance should not be nil'); Assert.IsNotNull(funcLazy, 'TMycFuncLazy<Integer> instance should not be nil');
changedState := funcLazy.GetChanged; changedState := funcLazy.GetChanged;
Assert.IsNotNull(changedState, 'funcLazy.GetChanged should return a valid TState.IState'); Assert.IsNotNull(changedState, 'funcLazy.GetChanged should return a valid TState.IState');
@@ -172,7 +172,7 @@ begin
expectedValue := 50; expectedValue := 50;
funcLazy := funcLazy :=
TMycFuncLazy<Integer>.Create( TMycFuncLazy<Integer>.Create(
sourceDirty.State, sourceDirty.State.Signal,
function: Integer function: Integer
begin begin
procExecuted := True; procExecuted := True;
@@ -200,7 +200,7 @@ begin
sourceDirty := TFlag.CreateFlag; sourceDirty := TFlag.CreateFlag;
sourceDirty.Reset; sourceDirty.Reset;
initialProcValue := 33; initialProcValue := 33;
funcLazy := TMycFuncLazy<Integer>.Create(sourceDirty.State, function: Integer begin Result := initialProcValue; end); funcLazy := TMycFuncLazy<Integer>.Create(sourceDirty.State.Signal, function: Integer begin Result := initialProcValue; end);
Helper_ConsumeInitialPop(funcLazy, initialProcValue); Helper_ConsumeInitialPop(funcLazy, initialProcValue);
Assert.IsFalse(funcLazy.GetChanged.IsSet, 'After initial Pop and no source change, GetChanged.IsSet should be false'); Assert.IsFalse(funcLazy.GetChanged.IsSet, 'After initial Pop and no source change, GetChanged.IsSet should be false');
end; end;
@@ -220,7 +220,7 @@ begin
procExecutedCount := 0; procExecutedCount := 0;
funcLazy := funcLazy :=
TMycFuncLazy<Integer>.Create( TMycFuncLazy<Integer>.Create(
sourceDirty.State, sourceDirty.State.Signal,
function: Integer function: Integer
begin begin
Inc(procExecutedCount); Inc(procExecutedCount);
@@ -244,7 +244,7 @@ begin
sourceDirty := TFlag.CreateFlag; sourceDirty := TFlag.CreateFlag;
sourceDirty.Reset; sourceDirty.Reset;
initialProcValue := 20; initialProcValue := 20;
funcLazy := TMycFuncLazy<Integer>.Create(sourceDirty.State, function: Integer begin Result := initialProcValue; end); funcLazy := TMycFuncLazy<Integer>.Create(sourceDirty.State.Signal, function: Integer begin Result := initialProcValue; end);
Helper_ConsumeInitialPop(funcLazy, initialProcValue); Helper_ConsumeInitialPop(funcLazy, initialProcValue);
sourceDirty.Notify; sourceDirty.Notify;
changedState := funcLazy.GetChanged; changedState := funcLazy.GetChanged;
@@ -265,7 +265,7 @@ begin
procCallCount := 0; procCallCount := 0;
funcLazy := funcLazy :=
TMycFuncLazy<Integer>.Create( TMycFuncLazy<Integer>.Create(
sourceDirty.State, sourceDirty.State.Signal,
function: Integer function: Integer
begin begin
Inc(procCallCount); Inc(procCallCount);
@@ -302,7 +302,7 @@ begin
procCallCount := 0; procCallCount := 0;
funcLazy := funcLazy :=
TMycFuncLazy<Integer>.Create( TMycFuncLazy<Integer>.Create(
sourceDirty.State, sourceDirty.State.Signal,
function: Integer function: Integer
begin begin
Inc(procCallCount); Inc(procCallCount);
@@ -338,7 +338,7 @@ begin
funcLazy := funcLazy :=
TMycFuncLazy<Integer>.Create( TMycFuncLazy<Integer>.Create(
sourceDirty.State, sourceDirty.State.Signal,
function: Integer function: Integer
begin begin
Inc(procCallCount); Inc(procCallCount);
@@ -391,7 +391,7 @@ var
begin begin
sourceDirty := TFlag.CreateFlag; sourceDirty := TFlag.CreateFlag;
sourceDirty.Reset; sourceDirty.Reset;
funcLazyObj := TMycFuncLazy<Integer>.Create(sourceDirty.State, function: Integer begin Result := 1; end); funcLazyObj := TMycFuncLazy<Integer>.Create(sourceDirty.State.Signal, function: Integer begin Result := 1; end);
Assert.IsTrue(funcLazyObj.Pop(tempVal), 'Initial Pop should succeed'); Assert.IsTrue(funcLazyObj.Pop(tempVal), 'Initial Pop should succeed');
funcLazyObj.Destroy; funcLazyObj.Destroy;
Assert.WillNotRaise( Assert.WillNotRaise(
@@ -411,13 +411,13 @@ var
expectedValue: Integer; expectedValue: Integer;
procExecuted: Boolean; procExecuted: Boolean;
begin begin
sourceDirty := TFlag.CreateFlag; sourceDirty := TFlag.CreateFlag( true );
Assert.IsTrue(sourceDirty.State.IsSet, 'SourceDirty should be initially set for this test scenario'); Assert.IsTrue(sourceDirty.State.IsSet, 'SourceDirty should be initially set for this test scenario');
expectedValue := 70; expectedValue := 70;
procExecuted := False; procExecuted := False;
funcLazy := funcLazy :=
TMycFuncLazy<Integer>.Create( TMycFuncLazy<Integer>.Create(
sourceDirty.State, sourceDirty.State.Signal,
function: Integer function: Integer
begin begin
procExecuted := True; procExecuted := True;
+11 -11
View File
@@ -145,7 +145,7 @@ begin
// FChangingSignal is reset in Setup // FChangingSignal is reset in Setup
lazyIntf := lazyIntf :=
TLazy<Integer>.Construct( TLazy<Integer>.Construct(
FChangingSignal.State, FChangingSignal.State.Signal,
function: Integer function: Integer
begin begin
procExecuted := True; procExecuted := True;
@@ -170,7 +170,7 @@ begin
expectedValue := 20; expectedValue := 20;
lazyIntf := lazyIntf :=
TLazy<Integer>.Construct( TLazy<Integer>.Construct(
FChangingSignal.State, FChangingSignal.State.Signal,
function: Integer function: Integer
begin begin
procExecuted := True; procExecuted := True;
@@ -190,7 +190,7 @@ var
expectedValue: Integer; expectedValue: Integer;
begin begin
expectedValue := 30; expectedValue := 30;
lazyIntf := TLazy<Integer>.Construct(FChangingSignal.State, function: Integer begin Result := expectedValue; end); lazyIntf := TLazy<Integer>.Construct(FChangingSignal.State.Signal, function: Integer begin Result := expectedValue; end);
lazyRec := lazyIntf; lazyRec := lazyIntf;
ConsumeInitialPop(lazyRec, expectedValue, 'TestConstruct_StateInteraction_SignalTriggersChanged (Initial)'); ConsumeInitialPop(lazyRec, expectedValue, 'TestConstruct_StateInteraction_SignalTriggersChanged (Initial)');
@@ -212,7 +212,7 @@ begin
procCallCount := 0; procCallCount := 0;
lazyIntf := lazyIntf :=
TLazy<Integer>.Construct( TLazy<Integer>.Construct(
FChangingSignal.State, FChangingSignal.State.Signal,
function: Integer function: Integer
begin begin
Inc(procCallCount); Inc(procCallCount);
@@ -243,7 +243,7 @@ begin
procCallCount := 0; procCallCount := 0;
lazyIntf := lazyIntf :=
TLazy<Integer>.Construct( TLazy<Integer>.Construct(
FChangingSignal.State, FChangingSignal.State.Signal,
function: Integer function: Integer
begin begin
Inc(procCallCount); Inc(procCallCount);
@@ -286,7 +286,7 @@ begin
localChangingSignal := TFlag.CreateFlag; localChangingSignal := TFlag.CreateFlag;
localChangingSignal.Reset; localChangingSignal.Reset;
lazyIntf := TLazy<Integer>.Construct(localChangingSignal.State, function: Integer begin Result := 1; end); lazyIntf := TLazy<Integer>.Construct(localChangingSignal.State.Signal, function: Integer begin Result := 1; end);
Assert.IsNotNull(lazyIntf, 'Constructed lazy interface should not be nil'); Assert.IsNotNull(lazyIntf, 'Constructed lazy interface should not be nil');
// Simulate usage and release of the lazy object // Simulate usage and release of the lazy object
@@ -317,7 +317,7 @@ var
expectedValue: Integer; expectedValue: Integer;
begin begin
expectedValue := 60; expectedValue := 60;
originalLazyIntf := TLazy<Integer>.Construct(FChangingSignal.State, function: Integer begin Result := expectedValue; end); originalLazyIntf := TLazy<Integer>.Construct(FChangingSignal.State.Signal, function: Integer begin Result := expectedValue; end);
// originalLazyIntf.Changed.IsSet is true by design // originalLazyIntf.Changed.IsSet is true by design
wrappedLazyRec := TLazy<Integer>.Create(originalLazyIntf); wrappedLazyRec := TLazy<Integer>.Create(originalLazyIntf);
@@ -344,7 +344,7 @@ begin
procCallCount := 0; procCallCount := 0;
originalLazyIntf := originalLazyIntf :=
TLazy<Integer>.Construct( TLazy<Integer>.Construct(
FChangingSignal.State, FChangingSignal.State.Signal,
function: Integer function: Integer
begin begin
Inc(procCallCount); Inc(procCallCount);
@@ -381,7 +381,7 @@ var
expectedValue: Integer; expectedValue: Integer;
begin begin
expectedValue := 80; expectedValue := 80;
lazyIntf := TLazy<Integer>.Construct(FChangingSignal.State, function: Integer begin Result := expectedValue; end); lazyIntf := TLazy<Integer>.Construct(FChangingSignal.State.Signal, function: Integer begin Result := expectedValue; end);
Assert.IsNotNull(lazyIntf, 'Interface should be assigned'); Assert.IsNotNull(lazyIntf, 'Interface should be assigned');
lazyRec := lazyIntf; // Implicit conversion: ILazy<T> to TLazy<T> lazyRec := lazyIntf; // Implicit conversion: ILazy<T> to TLazy<T>
@@ -400,7 +400,7 @@ var
expectedValue: Integer; expectedValue: Integer;
begin begin
expectedValue := 90; expectedValue := 90;
lazyIntfFromConstruct := TLazy<Integer>.Construct(FChangingSignal.State, function: Integer begin Result := expectedValue; end); lazyIntfFromConstruct := TLazy<Integer>.Construct(FChangingSignal.State.Signal, function: Integer begin Result := expectedValue; end);
lazyRec.Create(lazyIntfFromConstruct); // Explicitly create record lazyRec.Create(lazyIntfFromConstruct); // Explicitly create record
lazyIntfFromRecord := lazyRec; // Implicit conversion: TLazy<T> to ILazy<T> lazyIntfFromRecord := lazyRec; // Implicit conversion: TLazy<T> to ILazy<T>
@@ -426,7 +426,7 @@ begin
procExecuted := False; procExecuted := False;
lazyIntf := lazyIntf :=
TLazy<Integer>.Construct( TLazy<Integer>.Construct(
FChangingSignal.State, FChangingSignal.State.Signal,
function: Integer function: Integer
begin begin
procExecuted := True; procExecuted := True;
+5 -3
View File
@@ -105,7 +105,7 @@ end;
function TTestMycDirtyFlag.CreateAndPrepareDirtyFlag(StartDirty: Boolean = True): TFlag.IFlag; function TTestMycDirtyFlag.CreateAndPrepareDirtyFlag(StartDirty: Boolean = True): TFlag.IFlag;
begin begin
Result := TFlag.CreateFlag; // Initially dirty Result := TFlag.CreateFlag( true ); // Initially dirty
if not StartDirty then if not StartDirty then
Result.Reset; // Reset to make it clean Result.Reset; // Reset to make it clean
Assert.AreEqual(StartDirty, Result.State.IsSet, 'CreateAndPrepareDirtyFlag initial state incorrect.'); Assert.AreEqual(StartDirty, Result.State.IsSet, 'CreateAndPrepareDirtyFlag initial state incorrect.');
@@ -127,8 +127,10 @@ procedure TTestMycDirtyFlag.TestCreate_InitialStateIsDirty;
var var
dirtyFlag: TFlag.IFlag; dirtyFlag: TFlag.IFlag;
begin begin
dirtyFlag := TFlag.CreateFlag; dirtyFlag := TFlag.CreateFlag( true );
Assert.IsTrue(dirtyFlag.State.IsSet, 'Newly created dirty flag should be IsSet (dirty).'); Assert.IsTrue(dirtyFlag.State.IsSet, 'Newly created dirty flag should be IsSet.');
dirtyFlag := TFlag.CreateFlag( false );
Assert.IsFalse(dirtyFlag.State.IsSet, 'Newly created dirty flag should not be IsSet.');
end; end;
procedure TTestMycDirtyFlag.TestReset_FromDirtyState_BecomesCleanAndReturnsTrue; procedure TTestMycDirtyFlag.TestReset_FromDirtyState_BecomesCleanAndReturnsTrue;
+3 -3
View File
@@ -403,7 +403,7 @@ begin
FDataServer := ADataServer; FDataServer := ADataServer;
FSymbol := ASymbol; FSymbol := ASymbol;
FNextReady := TFlag.CreateFlag; FNextReady := TFlag.CreateFlag;
FHasData := TEvent.CreateRouter(FNextReady.State.AsSignal); FHasData := TEvent.CreateRouter(FNextReady.State.Signal);
end; end;
destructor TAuraFileStream<T>.Destroy; destructor TAuraFileStream<T>.Destroy;
@@ -428,7 +428,7 @@ begin
begin begin
Result.FileInfo := FileInfo; Result.FileInfo := FileInfo;
Result.Data := FDataServer.LoadDataFile(FileInfo); Result.Data := FDataServer.LoadDataFile(FileInfo);
Result.Data.Done.Subscribe(FNextReady); Result.Data.Done.Signal.Subscribe(FNextReady);
end; end;
end end
); );
@@ -525,7 +525,7 @@ begin
begin begin
Result.FileInfo := nextFileInfo; Result.FileInfo := nextFileInfo;
Result.Data := FDataServer.LoadDataFile(nextFileInfo); Result.Data := FDataServer.LoadDataFile(nextFileInfo);
Result.Data.Done.Subscribe(FNextReady); Result.Data.Done.Signal.Subscribe(FNextReady);
end; end;
end; end;
end end