Refactoring IState - ISignal
This commit is contained in:
+21
-24
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user