Moved signal interfaces inside records
This commit is contained in:
@@ -9,7 +9,7 @@ uses
|
||||
Myc.Futures;
|
||||
|
||||
type
|
||||
TMycFuture<T> = class abstract(TInterfacedObject, IMycFuture<T>)
|
||||
TMycFuture<T> = class abstract(TInterfacedObject, TFuture<T>.IFuture)
|
||||
protected
|
||||
function GetResult: T; virtual; abstract;
|
||||
function GetDone: TState; virtual; abstract;
|
||||
@@ -23,14 +23,14 @@ type
|
||||
|
||||
TMycGateFuncFuture<T> = class(TMycFuture<T>)
|
||||
private
|
||||
FInit: TSubscription;
|
||||
FDone: IMycLatch;
|
||||
FInit: TSignal.TSubscription;
|
||||
FDone: TLatch.ILatch;
|
||||
FResult: T;
|
||||
protected
|
||||
function GetResult: T; override;
|
||||
function GetDone: TState; override;
|
||||
public
|
||||
constructor Create(const ATaskManager: IMycTaskManager; const AGate: IMycState; AProc: TFunc<T>);
|
||||
constructor Create(const ATaskManager: IMycTaskManager; const AGate: TState.IState; AProc: TFunc<T>);
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
@@ -50,7 +50,7 @@ end;
|
||||
|
||||
{ TMycGateFuncFuture<T> }
|
||||
|
||||
constructor TMycGateFuncFuture<T>.Create(const ATaskManager: IMycTaskManager; const AGate: IMycState; AProc: TFunc<T>);
|
||||
constructor TMycGateFuncFuture<T>.Create(const ATaskManager: IMycTaskManager; const AGate: TState.IState; AProc: TFunc<T>);
|
||||
begin
|
||||
inherited Create;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ type
|
||||
TMycLazyBase<T> = class(TInterfacedObject, IMycLazy<T>)
|
||||
strict private
|
||||
FChanged: TFlag;
|
||||
FChangeState: TSubscription;
|
||||
FChangeState: TSignal.TSubscription;
|
||||
function GetChanged: TState;
|
||||
protected
|
||||
function GetValue: T; virtual; abstract;
|
||||
@@ -97,12 +97,12 @@ constructor TMycFuncLazy<T>.Create(const AChanged: TState; const AProc: TFunc<T>
|
||||
begin
|
||||
inherited Create(AChanged);
|
||||
FProc := AProc;
|
||||
Assert( Assigned(FProc) );
|
||||
Assert(Assigned(FProc));
|
||||
end;
|
||||
|
||||
function TMycFuncLazy<T>.GetValue: T;
|
||||
begin
|
||||
Result := FProc();
|
||||
Result := FProc();
|
||||
end;
|
||||
|
||||
{ TMycChainedLazy<T> }
|
||||
|
||||
+16
-16
@@ -10,7 +10,7 @@ uses
|
||||
type
|
||||
// TMycNullSignal implements a "null object" pattern for IMycState.
|
||||
// This state is always considered "set".
|
||||
TMycNullSignal = class(TInterfacedObject, IMycSignal)
|
||||
TMycNullSignal = class(TInterfacedObject, TSignal.ISignal)
|
||||
public
|
||||
function Subscribe(Subscriber: IMycSubscriber): Pointer;
|
||||
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
|
||||
@@ -18,14 +18,14 @@ type
|
||||
|
||||
// TMycNullState implements a "null object" pattern for IMycState.
|
||||
// This state is always considered "set".
|
||||
TMycNullState = class(TMycNullSignal, IMycState)
|
||||
TMycNullState = class(TMycNullSignal, TState.IState)
|
||||
protected
|
||||
// IMycState
|
||||
// TState.IState
|
||||
function GetIsSet: Boolean;
|
||||
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.
|
||||
TMycEvent = class(TInterfacedObject, IMycSignal, IMycEvent)
|
||||
TMycEvent = class(TInterfacedObject, TSignal.ISignal, TEvent.IEvent)
|
||||
strict private
|
||||
FSubscribers: TMycNotifyList<IMycSubscriber>;
|
||||
protected
|
||||
@@ -38,7 +38,7 @@ type
|
||||
procedure Trigger;
|
||||
end;
|
||||
|
||||
TMycNullEvent = class(TMycNullSignal, IMycEvent)
|
||||
TMycNullEvent = class(TMycNullSignal, TEvent.IEvent)
|
||||
private
|
||||
procedure Trigger;
|
||||
end;
|
||||
@@ -47,13 +47,13 @@ type
|
||||
// It is initialized with a count. Calls to its Notify method (as an IMycSubscriber)
|
||||
// decrement this count. When the count reaches zero, the latch transitions to the "set"
|
||||
// state (IsSet becomes true), notifies its current subscribers once, and then remains set.
|
||||
TMycLatch = class(TInterfacedObject, IMycState, IMycLatch)
|
||||
TMycLatch = class(TInterfacedObject, TState.IState, TLatch.ILatch)
|
||||
strict private
|
||||
FSubscribers: TMycNotifyList<IMycSubscriber>; // List of subscribers waiting for this latch to be set.
|
||||
private
|
||||
[volatile]
|
||||
FCount: Integer; // The internal countdown value for the latch.
|
||||
function GetState: TState; // Implementation for IMycLatch.GetState and IMycFlag.GetState.
|
||||
function GetState: TState; // Implementation for TLatch.ILatch.GetState and IFlag.GetState.
|
||||
protected
|
||||
function GetIsSet: Boolean;
|
||||
public
|
||||
@@ -62,7 +62,7 @@ type
|
||||
constructor Create(ACount: Integer);
|
||||
destructor Destroy; override;
|
||||
|
||||
// IMycSignal implementation
|
||||
// ISignal implementation
|
||||
function Subscribe(Subscriber: IMycSubscriber): Pointer;
|
||||
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
|
||||
|
||||
@@ -72,7 +72,7 @@ type
|
||||
function Notify: Boolean;
|
||||
end;
|
||||
|
||||
TMycNullLatch = class(TInterfacedObject, IMycLatch)
|
||||
TMycNullLatch = class(TInterfacedObject, TLatch.ILatch)
|
||||
private
|
||||
function GetState: TState;
|
||||
function Notify: Boolean;
|
||||
@@ -81,7 +81,7 @@ type
|
||||
// TMycFlag implements a resettable "dirty flag".
|
||||
// It can be explicitly set to dirty (via Notify) or reset to clean (via Reset).
|
||||
// Subscribers are notified of relevant state changes.
|
||||
TMycFlag = class(TInterfacedObject, IMycState, IMycFlag)
|
||||
TMycFlag = class(TInterfacedObject, TState.IState, TFlag.IFlag)
|
||||
strict private
|
||||
FSubscribers: TMycNotifyList<IMycSubscriber>; // List of subscribers interested in state changes of this dirty flag.
|
||||
private
|
||||
@@ -96,7 +96,7 @@ type
|
||||
destructor Destroy; override;
|
||||
|
||||
// Factory method to create a new TMycFlag instance.
|
||||
class function CreateDirty: IMycFlag; static;
|
||||
class function CreateDirty: TFlag.IFlag; static;
|
||||
|
||||
function Subscribe(Subscriber: IMycSubscriber): Pointer;
|
||||
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
|
||||
@@ -105,11 +105,11 @@ type
|
||||
// Sets this flag to dirty (true). Notifies subscribers if it transitioned from clean to dirty.
|
||||
function Notify: Boolean;
|
||||
|
||||
// IMycFlag implementation. Resets the flag to clean (false).
|
||||
// TFlag.IFlag implementation. Resets the flag to clean (false).
|
||||
function Reset: Boolean;
|
||||
end;
|
||||
|
||||
TMycNullFlag = class(TInterfacedObject, IMycFlag)
|
||||
TMycNullFlag = class(TInterfacedObject, TFlag.IFlag)
|
||||
private
|
||||
function GetState: TState;
|
||||
function Notify: Boolean;
|
||||
@@ -250,7 +250,7 @@ end;
|
||||
|
||||
function TMycLatch.GetState: TState;
|
||||
begin
|
||||
// TMycLatch itself implements IMycState.
|
||||
// TMycLatch itself implements TState.IState.
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
@@ -320,7 +320,7 @@ begin
|
||||
FSubscribers.Create;
|
||||
end;
|
||||
|
||||
class function TMycFlag.CreateDirty: IMycFlag;
|
||||
class function TMycFlag.CreateDirty: TFlag.IFlag;
|
||||
begin
|
||||
// Factory method to create a new TMycFlag instance.
|
||||
Result := TMycFlag.Create;
|
||||
@@ -346,7 +346,7 @@ end;
|
||||
|
||||
function TMycFlag.GetState: TState;
|
||||
begin
|
||||
// TMycFlag itself implements IMycState.
|
||||
// TMycFlag itself implements TState.IState.
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ type
|
||||
// Returns IMycState to await thread completion.
|
||||
// Exceptions within Proc are caught; the first one is stored
|
||||
// and can be re-raised in the main thread via WaitFor or Teardown.
|
||||
function CreateThread(const Proc: TProc): IMycState;
|
||||
function CreateThread(const Proc: TProc): TState.IState;
|
||||
|
||||
// Returns True if called from the main application thread.
|
||||
function InMainThread: Boolean;
|
||||
@@ -77,12 +77,12 @@ type
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
class function CreateAnonymousThread(const DbgName: String; const Proc: TProc): TThread;
|
||||
function CreateThread(const Proc: TProc): IMycState;
|
||||
function CreateThread(const Proc: TProc): TState.IState;
|
||||
procedure HandleException;
|
||||
procedure EnqueueJob(const Job: TProc);
|
||||
function Run(Job: TProc): IMycSubscriber;
|
||||
function CreateTask(const Gate: TState; const Proc: TProc): TSubscription;
|
||||
procedure WaitFor(State: IMycState);
|
||||
function CreateTask(const Gate: TState; const Proc: TProc): TSignal.TSubscription;
|
||||
procedure WaitFor(State: TState.IState);
|
||||
procedure Teardown;
|
||||
function InMainThread: Boolean;
|
||||
function InWorkerThread: Boolean;
|
||||
@@ -188,7 +188,7 @@ begin
|
||||
Result.NameThreadForDebugging(DbgName); // Set thread name for debugging
|
||||
end;
|
||||
|
||||
function TMycTaskFactory.CreateTask(const Gate: TState; const Proc: TProc): TSubscription;
|
||||
function TMycTaskFactory.CreateTask(const Gate: TState; const Proc: TProc): TSignal.TSubscription;
|
||||
begin
|
||||
if Gate.IsSet then
|
||||
begin
|
||||
@@ -201,9 +201,9 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TMycTaskFactory.CreateThread(const Proc: TProc): IMycState;
|
||||
function TMycTaskFactory.CreateThread(const Proc: TProc): TState.IState;
|
||||
var
|
||||
res: IMycLatch;
|
||||
res: TLatch.ILatch;
|
||||
capturedProc: TProc;
|
||||
begin
|
||||
// Create a latch that will be signaled when the proc finishes
|
||||
@@ -345,7 +345,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMycTaskFactory.WaitFor(State: IMycState);
|
||||
procedure TMycTaskFactory.WaitFor(State: TState.IState);
|
||||
var
|
||||
lock: TSemaphore; // This is System.SyncObjs.TSemaphore
|
||||
begin
|
||||
|
||||
+26
-25
@@ -9,45 +9,46 @@ uses
|
||||
|
||||
type
|
||||
// Represents the eventual result of an asynchronous operation.
|
||||
IMycFuture<T> = interface
|
||||
{$REGION 'property access'}
|
||||
function GetResult: T;
|
||||
function GetDone: TState;
|
||||
{$ENDREGION}
|
||||
// Provides access to the computed result.
|
||||
property Result: T read GetResult;
|
||||
// Provides access to the completion state.
|
||||
property Done: TState read GetDone;
|
||||
end;
|
||||
|
||||
TFuture<T> = record
|
||||
type
|
||||
IFuture = interface
|
||||
{$REGION 'property access'}
|
||||
function GetResult: T;
|
||||
function GetDone: TState;
|
||||
{$ENDREGION}
|
||||
// Provides access to the computed result.
|
||||
property Result: T read GetResult;
|
||||
// Provides access to the completion state.
|
||||
property Done: TState read GetDone;
|
||||
end;
|
||||
|
||||
private
|
||||
FFuture: IMycFuture<T>;
|
||||
function GetDone: IMycState; inline;
|
||||
FFuture: IFuture;
|
||||
function GetDone: TState.IState; inline;
|
||||
function GetResult: T; inline;
|
||||
|
||||
class var
|
||||
FNull: IMycFuture<T>;
|
||||
FNull: IFuture;
|
||||
|
||||
class constructor CreateClass;
|
||||
class destructor DestroyClass;
|
||||
|
||||
public
|
||||
constructor Create(const AFuture: IMycFuture<T>);
|
||||
constructor Create(const AFuture: IFuture);
|
||||
|
||||
class operator Implicit(const A: IMycFuture<T>): TFuture<T>; overload;
|
||||
class operator Implicit(const A: TFuture<T>): IMycFuture<T>; overload;
|
||||
class operator Implicit(const A: IFuture): TFuture<T>; overload;
|
||||
class operator Implicit(const A: TFuture<T>): IFuture; overload;
|
||||
|
||||
class function Construct(const Proc: TFunc<T>): TFuture<T>; overload; static;
|
||||
class function Construct(const Gate: IMycState; const Proc: TFunc<T>): TFuture<T>; overload; static;
|
||||
class function Construct(const Gate: TState.IState; const Proc: TFunc<T>): TFuture<T>; overload; static;
|
||||
|
||||
class property Null: IMycFuture<T> read FNull;
|
||||
class property Null: IFuture read FNull;
|
||||
|
||||
function Chain<S>(const Proc: TFunc<T, S>): TFuture<S>;
|
||||
|
||||
function WaitFor: T;
|
||||
|
||||
property Done: IMycState read GetDone;
|
||||
property Done: TState.IState read GetDone;
|
||||
property Result: T read GetResult;
|
||||
end;
|
||||
|
||||
@@ -57,7 +58,7 @@ uses
|
||||
Myc.Core.Futures,
|
||||
Myc.Core.Tasks;
|
||||
|
||||
constructor TFuture<T>.Create(const AFuture: IMycFuture<T>);
|
||||
constructor TFuture<T>.Create(const AFuture: IFuture);
|
||||
begin
|
||||
FFuture := AFuture;
|
||||
if not Assigned(FFuture) then
|
||||
@@ -87,12 +88,12 @@ begin
|
||||
Result := TMycGateFuncFuture<T>.Create(TaskManager, nil, Proc);
|
||||
end;
|
||||
|
||||
class function TFuture<T>.Construct(const Gate: IMycState; const Proc: TFunc<T>): TFuture<T>;
|
||||
class function TFuture<T>.Construct(const Gate: TState.IState; const Proc: TFunc<T>): TFuture<T>;
|
||||
begin
|
||||
Result := TMycGateFuncFuture<T>.Create(TaskManager, Gate, Proc);
|
||||
end;
|
||||
|
||||
function TFuture<T>.GetDone: IMycState;
|
||||
function TFuture<T>.GetDone: TState.IState;
|
||||
begin
|
||||
Result := FFuture.Done;
|
||||
end;
|
||||
@@ -108,12 +109,12 @@ begin
|
||||
Result := FFuture.Result;
|
||||
end;
|
||||
|
||||
class operator TFuture<T>.Implicit(const A: IMycFuture<T>): TFuture<T>;
|
||||
class operator TFuture<T>.Implicit(const A: IFuture): TFuture<T>;
|
||||
begin
|
||||
Result.Create(A);
|
||||
end;
|
||||
|
||||
class operator TFuture<T>.Implicit(const A: TFuture<T>): IMycFuture<T>;
|
||||
class operator TFuture<T>.Implicit(const A: TFuture<T>): IFuture;
|
||||
begin
|
||||
Result := A.FFuture;
|
||||
end;
|
||||
|
||||
+5
-5
@@ -25,7 +25,7 @@ type
|
||||
TLazy<T> = record
|
||||
private
|
||||
FLazy: IMycLazy<T>;
|
||||
function GetChanged: IMycState; inline;
|
||||
function GetChanged: TState.IState; inline;
|
||||
class var
|
||||
FNull: IMycLazy<T>;
|
||||
class constructor CreateClass;
|
||||
@@ -33,7 +33,7 @@ type
|
||||
public
|
||||
constructor Create(const ALazy: IMycLazy<T>);
|
||||
|
||||
class function Construct(const Changing: IMycState; const Proc: TFunc<T>): IMycLazy<T>; overload; static;
|
||||
class function Construct(const Changing: TState.IState; const Proc: TFunc<T>): IMycLazy<T>; overload; static;
|
||||
class function Construct(const Value: IMycLazy<T>): IMycLazy<T>; overload; static;
|
||||
|
||||
class operator Implicit(const A: IMycLazy<T>): TLazy<T>; overload;
|
||||
@@ -41,7 +41,7 @@ type
|
||||
|
||||
function Pop(out Res: T): Boolean; inline;
|
||||
|
||||
property Changed: IMycState read GetChanged;
|
||||
property Changed: TState.IState read GetChanged;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@@ -56,7 +56,7 @@ begin
|
||||
FLazy := FNull;
|
||||
end;
|
||||
|
||||
class function TLazy<T>.Construct(const Changing: IMycState; const Proc: TFunc<T>): IMycLazy<T>;
|
||||
class function TLazy<T>.Construct(const Changing: TState.IState; const Proc: TFunc<T>): IMycLazy<T>;
|
||||
begin
|
||||
Result := TMycFuncLazy<T>.Create(Changing, Proc);
|
||||
end;
|
||||
@@ -71,7 +71,7 @@ begin
|
||||
Result := TMycChainedLazy<T>.Create(Value);
|
||||
end;
|
||||
|
||||
function TLazy<T>.GetChanged: IMycState;
|
||||
function TLazy<T>.GetChanged: TState.IState;
|
||||
begin
|
||||
Result := FLazy.Changed;
|
||||
end;
|
||||
|
||||
+121
-119
@@ -10,160 +10,168 @@ type
|
||||
function Notify: Boolean;
|
||||
end;
|
||||
|
||||
TSubscriptionTag = Pointer;
|
||||
|
||||
IMycSignal = interface
|
||||
function Subscribe(Subscriber: IMycSubscriber): TSubscriptionTag;
|
||||
procedure Unsubscribe(Tag: TSubscriptionTag);
|
||||
end;
|
||||
|
||||
TSubscription = record
|
||||
private
|
||||
FState: IMycSignal;
|
||||
FTag: TSubscriptionTag;
|
||||
constructor Create(const AState: IMycSignal; ATag: Pointer);
|
||||
public
|
||||
class operator Initialize(out Dest: TSubscription);
|
||||
// Unsubscribes from the associated TState.
|
||||
procedure Unsubscribe;
|
||||
end;
|
||||
|
||||
TSignal = record
|
||||
type
|
||||
TSubscriptionTag = Pointer;
|
||||
|
||||
ISignal = interface
|
||||
function Subscribe(Subscriber: IMycSubscriber): TSubscriptionTag;
|
||||
procedure Unsubscribe(Tag: TSubscriptionTag);
|
||||
end;
|
||||
|
||||
TSubscription = record
|
||||
private
|
||||
FSignal: ISignal;
|
||||
FTag: TSubscriptionTag;
|
||||
constructor Create(const ASignal: ISignal; ATag: TSubscriptionTag);
|
||||
public
|
||||
class operator Initialize(out Dest: TSubscription);
|
||||
// Unsubscribes from the associated signal
|
||||
procedure Unsubscribe;
|
||||
end;
|
||||
|
||||
strict private
|
||||
class var
|
||||
FNull: IMycSignal;
|
||||
class var
|
||||
FNull: ISignal;
|
||||
class constructor ClassCreate;
|
||||
|
||||
private
|
||||
FSignal: IMycSignal;
|
||||
FSignal: ISignal;
|
||||
|
||||
public
|
||||
constructor Create(const ASignal: IMycSignal);
|
||||
constructor Create(const ASignal: ISignal);
|
||||
class operator Initialize(out Dest: TSignal);
|
||||
class operator Implicit(const A: IMycSignal): TSignal; overload;
|
||||
class operator Implicit(const A: TSignal): IMycSignal; overload;
|
||||
class operator Implicit(const A: ISignal): TSignal; overload;
|
||||
class operator Implicit(const A: TSignal): ISignal; overload;
|
||||
|
||||
function Subscribe(Subscriber: IMycSubscriber): TSubscription; inline;
|
||||
procedure Unsubscribe(Tag: Pointer); inline;
|
||||
|
||||
class property Null: IMycSignal read FNull;
|
||||
end;
|
||||
|
||||
IMycEvent = interface( IMycSignal )
|
||||
procedure Trigger;
|
||||
class property Null: ISignal read FNull;
|
||||
end;
|
||||
|
||||
TEvent = record
|
||||
type
|
||||
IEvent = interface(TSignal.ISignal)
|
||||
procedure Trigger;
|
||||
end;
|
||||
|
||||
strict private
|
||||
class var
|
||||
FNull: IMycEvent;
|
||||
FNull: IEvent;
|
||||
class constructor ClassCreate;
|
||||
|
||||
private
|
||||
FEvent: IMycEvent;
|
||||
FEvent: IEvent;
|
||||
|
||||
public
|
||||
constructor Create(const AEvent: IMycEvent);
|
||||
constructor Create(const AEvent: IEvent);
|
||||
class operator Initialize(out Dest: TEvent);
|
||||
class operator Implicit(const A: IMycEvent): TEvent; overload;
|
||||
class operator Implicit(const A: TEvent): IMycEvent; overload;
|
||||
class operator Implicit(const A: IEvent): TEvent; overload;
|
||||
class operator Implicit(const A: TEvent): IEvent; overload;
|
||||
|
||||
class property Null: IMycEvent read FNull;
|
||||
class property Null: IEvent read FNull;
|
||||
|
||||
function Subscribe(Subscriber: IMycSubscriber): TSubscription; inline;
|
||||
function Subscribe(Subscriber: IMycSubscriber): TSignal.TSubscription; inline;
|
||||
procedure Unsubscribe(Tag: Pointer); inline;
|
||||
end;
|
||||
|
||||
IMycState = interface(IMycSignal)
|
||||
// Represents a subscribable TState that can be queried.
|
||||
{$REGION 'property access'}
|
||||
function GetIsSet: Boolean;
|
||||
{$ENDREGION}
|
||||
// IsSet is true if the TState has been reached or the condition is met.
|
||||
property IsSet: Boolean read GetIsSet;
|
||||
end;
|
||||
TState = record
|
||||
type
|
||||
IState = interface(TSignal.ISignal)
|
||||
{$REGION 'property access'}
|
||||
function GetIsSet: Boolean;
|
||||
{$ENDREGION}
|
||||
// IsSet is true if the TState has been reached or the condition is met.
|
||||
property IsSet: Boolean read GetIsSet;
|
||||
end;
|
||||
|
||||
TState = record // helper for IMycState
|
||||
strict private
|
||||
class var
|
||||
FNull: IMycState;
|
||||
FNull: IState;
|
||||
class constructor ClassCreate;
|
||||
|
||||
private
|
||||
FState: IMycState;
|
||||
FState: IState;
|
||||
function GetIsSet: Boolean; inline;
|
||||
|
||||
public
|
||||
constructor Create(const AState: IMycState);
|
||||
constructor Create(const AState: IState);
|
||||
class operator Initialize(out Dest: TState);
|
||||
class operator Implicit(const A: IMycState): TState; overload;
|
||||
class operator Implicit(const A: TState): IMycState; overload;
|
||||
class operator Implicit(const A: IState): TState; overload;
|
||||
class operator Implicit(const A: TState): IState; overload;
|
||||
|
||||
class function All(const States: TArray<TState>): TState; static;
|
||||
class function Any(const States: TArray<TState>): TState; static;
|
||||
|
||||
class property Null: IMycState read FNull;
|
||||
class property Null: IState read FNull;
|
||||
|
||||
function Subscribe(Subscriber: IMycSubscriber): TSubscription; inline;
|
||||
function Subscribe(Subscriber: IMycSubscriber): TSignal.TSubscription; inline;
|
||||
procedure Unsubscribe(Tag: Pointer); inline;
|
||||
|
||||
property IsSet: Boolean read GetIsSet;
|
||||
end;
|
||||
|
||||
IMycLatch = interface(IMycSubscriber)
|
||||
function GetState: TState;
|
||||
property State: TState read GetState;
|
||||
end;
|
||||
|
||||
// A latch is a specific type of event that, once set, remains set (non-resettable).
|
||||
// It becomes set when the internal countdown reaches zero.
|
||||
TLatch = record
|
||||
type
|
||||
ILatch = interface(IMycSubscriber)
|
||||
function GetState: TState;
|
||||
property State: TState read GetState;
|
||||
end;
|
||||
|
||||
strict private
|
||||
class var
|
||||
FNull: IMycLatch;
|
||||
FNull: ILatch;
|
||||
class constructor ClassCreate;
|
||||
|
||||
private
|
||||
FLatch: IMycLatch;
|
||||
FLatch: ILatch;
|
||||
function GetState: TState; inline;
|
||||
|
||||
public
|
||||
constructor Create(const ALatch: IMycLatch);
|
||||
constructor Create(const ALatch: ILatch);
|
||||
class operator Initialize(out Dest: TLatch);
|
||||
class operator Implicit(const A: IMycLatch): TLatch; overload;
|
||||
class operator Implicit(const A: TLatch): IMycLatch; overload;
|
||||
class operator Implicit(const A: ILatch): TLatch; overload;
|
||||
class operator Implicit(const A: TLatch): ILatch; overload;
|
||||
|
||||
// A latch is a specific type of event that, once set, remains set (non-resettable).
|
||||
// It becomes set when the internal countdown reaches zero.
|
||||
class function CreateLatch(Count: Integer): TLatch; static;
|
||||
|
||||
class function Enqueue(var Gate: TLatch; Count: Integer = 1): TState; static;
|
||||
|
||||
class property Null: IMycLatch read FNull;
|
||||
class property Null: ILatch read FNull;
|
||||
|
||||
function Notify: Boolean; inline;
|
||||
|
||||
property State: TState read GetState;
|
||||
end;
|
||||
|
||||
// IMycFlag represents a resettable flag, typically indicating if a State is "dirty" (requiring attention) or "clean".
|
||||
IMycFlag = interface(IMycSubscriber)
|
||||
function GetState: TState;
|
||||
// Resets the flag to its "clean" (not set / not dirty) State.
|
||||
// Returns true if the flag was actually dirty before this reset, false otherwise.
|
||||
function Reset: Boolean;
|
||||
property State: TState read GetState;
|
||||
end;
|
||||
|
||||
// TFlag represents a resettable flag, typically indicating if a State is "dirty" (requiring attention) or "clean".
|
||||
TFlag = record
|
||||
type
|
||||
IFlag = interface(IMycSubscriber)
|
||||
function GetState: TState;
|
||||
function Reset: Boolean;
|
||||
property State: TState read GetState;
|
||||
end;
|
||||
|
||||
strict private
|
||||
class var
|
||||
FNull: IMycFlag;
|
||||
FNull: IFlag;
|
||||
class constructor ClassCreate;
|
||||
|
||||
private
|
||||
FDirty: IMycFlag;
|
||||
FDirty: IFlag;
|
||||
function GetState: TState; inline;
|
||||
|
||||
public
|
||||
constructor Create(const ADirty: IMycFlag);
|
||||
constructor Create(const ADirty: IFlag);
|
||||
class operator Initialize(out Dest: TFlag);
|
||||
class operator Implicit(const A: IMycFlag): TFlag; overload;
|
||||
class operator Implicit(const A: TFlag): IMycFlag; overload;
|
||||
class operator Implicit(const A: IFlag): TFlag; overload;
|
||||
class operator Implicit(const A: TFlag): IFlag; overload;
|
||||
|
||||
class function CreateFlag: IMycFlag; static;
|
||||
class property Null: IMycFlag read FNull;
|
||||
class function CreateFlag: IFlag; static;
|
||||
class property Null: IFlag read FNull;
|
||||
|
||||
function Notify: Boolean; inline;
|
||||
function Reset: Boolean;
|
||||
@@ -177,31 +185,31 @@ uses
|
||||
Myc.Core.Notifier,
|
||||
Myc.Core.Signals;
|
||||
|
||||
{ TState.TSubscription }
|
||||
{ TSignal.TSubscription }
|
||||
|
||||
constructor TSubscription.Create(const AState: IMycSignal; ATag: Pointer);
|
||||
constructor TSignal.TSubscription.Create(const ASignal: ISignal; ATag: TSubscriptionTag);
|
||||
begin
|
||||
Assert(Assigned(AState));
|
||||
FState := AState;
|
||||
FSignal := ASignal;
|
||||
FTag := ATag;
|
||||
Assert(Assigned(FSignal));
|
||||
end;
|
||||
|
||||
procedure TSubscription.Unsubscribe;
|
||||
procedure TSignal.TSubscription.Unsubscribe;
|
||||
begin
|
||||
FState.Unsubscribe(FTag);
|
||||
FState := TState.Null;
|
||||
FSignal.Unsubscribe(FTag);
|
||||
FSignal := TSignal.Null;
|
||||
FTag := nil;
|
||||
end;
|
||||
|
||||
class operator TSubscription.Initialize(out Dest: TSubscription);
|
||||
class operator TSignal.TSubscription.Initialize(out Dest: TSubscription);
|
||||
begin
|
||||
Dest.FState := TState.Null;
|
||||
Dest.FSignal := TSignal.Null;
|
||||
Dest.FTag := nil;
|
||||
end;
|
||||
|
||||
{ TState }
|
||||
|
||||
constructor TState.Create(const AState: IMycState);
|
||||
constructor TState.Create(const AState: IState);
|
||||
begin
|
||||
FState := AState;
|
||||
if not Assigned(FState) then
|
||||
@@ -216,7 +224,7 @@ end;
|
||||
|
||||
class function TState.All(const States: TArray<TState>): TState;
|
||||
var
|
||||
Latch: IMycLatch;
|
||||
Latch: TLatch.ILatch;
|
||||
begin
|
||||
Latch := TLatch.CreateLatch(Length(States));
|
||||
for var i := 0 to High(States) do
|
||||
@@ -226,7 +234,7 @@ end;
|
||||
|
||||
class function TState.Any(const States: TArray<TState>): TState;
|
||||
var
|
||||
Latch: IMycLatch;
|
||||
Latch: TLatch.ILatch;
|
||||
begin
|
||||
if Length(States) = 0 then
|
||||
begin
|
||||
@@ -246,9 +254,9 @@ begin
|
||||
Result := FState.IsSet;
|
||||
end;
|
||||
|
||||
function TState.Subscribe(Subscriber: IMycSubscriber): TSubscription;
|
||||
function TState.Subscribe(Subscriber: IMycSubscriber): TSignal.TSubscription;
|
||||
begin
|
||||
Result := TSubscription.Create(FState, FState.Subscribe(Subscriber));
|
||||
Result := TSignal.TSubscription.Create(FState, FState.Subscribe(Subscriber));
|
||||
end;
|
||||
|
||||
procedure TState.Unsubscribe(Tag: Pointer);
|
||||
@@ -256,12 +264,12 @@ begin
|
||||
FState.Unsubscribe(Tag);
|
||||
end;
|
||||
|
||||
class operator TState.Implicit(const A: TState): IMycState;
|
||||
class operator TState.Implicit(const A: TState): IState;
|
||||
begin
|
||||
Result := A.FState;
|
||||
end;
|
||||
|
||||
class operator TState.Implicit(const A: IMycState): TState;
|
||||
class operator TState.Implicit(const A: IState): TState;
|
||||
begin
|
||||
Result.Create(A);
|
||||
end;
|
||||
@@ -273,7 +281,7 @@ end;
|
||||
|
||||
{ TEvent }
|
||||
|
||||
constructor TEvent.Create(const AEvent: IMycEvent);
|
||||
constructor TEvent.Create(const AEvent: IEvent);
|
||||
begin
|
||||
FEvent := AEvent;
|
||||
if not Assigned(FEvent) then
|
||||
@@ -285,9 +293,9 @@ begin
|
||||
FNull := TMycNullEvent.Create();
|
||||
end;
|
||||
|
||||
function TEvent.Subscribe(Subscriber: IMycSubscriber): TSubscription;
|
||||
function TEvent.Subscribe(Subscriber: IMycSubscriber): TSignal.TSubscription;
|
||||
begin
|
||||
Result := TSubscription.Create(FEvent, FEvent.Subscribe(Subscriber));
|
||||
Result := TSignal.TSubscription.Create(FEvent, FEvent.Subscribe(Subscriber));
|
||||
end;
|
||||
|
||||
procedure TEvent.Unsubscribe(Tag: Pointer);
|
||||
@@ -295,12 +303,12 @@ begin
|
||||
FEvent.Unsubscribe(Tag);
|
||||
end;
|
||||
|
||||
class operator TEvent.Implicit(const A: TEvent): IMycEvent;
|
||||
class operator TEvent.Implicit(const A: TEvent): IEvent;
|
||||
begin
|
||||
Result := A.FEvent;
|
||||
end;
|
||||
|
||||
class operator TEvent.Implicit(const A: IMycEvent): TEvent;
|
||||
class operator TEvent.Implicit(const A: IEvent): TEvent;
|
||||
begin
|
||||
Result.Create(A);
|
||||
end;
|
||||
@@ -317,14 +325,14 @@ begin
|
||||
FNull := TMycNullFlag.Create;
|
||||
end;
|
||||
|
||||
constructor TFlag.Create(const ADirty: IMycFlag);
|
||||
constructor TFlag.Create(const ADirty: IFlag);
|
||||
begin
|
||||
FDirty := ADirty;
|
||||
if not Assigned(FDirty) then
|
||||
FDirty := FNull;
|
||||
end;
|
||||
|
||||
class function TFlag.CreateFlag: IMycFlag;
|
||||
class function TFlag.CreateFlag: IFlag;
|
||||
begin
|
||||
Result := TMycFlag.Create;
|
||||
end;
|
||||
@@ -344,12 +352,12 @@ begin
|
||||
Result := FDirty.Reset;
|
||||
end;
|
||||
|
||||
class operator TFlag.Implicit(const A: IMycFlag): TFlag;
|
||||
class operator TFlag.Implicit(const A: IFlag): TFlag;
|
||||
begin
|
||||
Result.Create(A);
|
||||
end;
|
||||
|
||||
class operator TFlag.Implicit(const A: TFlag): IMycFlag;
|
||||
class operator TFlag.Implicit(const A: TFlag): IFlag;
|
||||
begin
|
||||
Result := A.FDirty;
|
||||
end;
|
||||
@@ -367,8 +375,7 @@ begin
|
||||
FNull := TMycNullLatch.Create;
|
||||
end;
|
||||
|
||||
|
||||
constructor TLatch.Create(const ALatch: IMycLatch);
|
||||
constructor TLatch.Create(const ALatch: TLatch.ILatch);
|
||||
begin
|
||||
FLatch := ALatch;
|
||||
if not Assigned(FLatch) then
|
||||
@@ -401,12 +408,12 @@ begin
|
||||
Result := FLatch.Notify;
|
||||
end;
|
||||
|
||||
class operator TLatch.Implicit(const A: IMycLatch): TLatch;
|
||||
class operator TLatch.Implicit(const A: TLatch.ILatch): TLatch;
|
||||
begin
|
||||
Result.Create(A);
|
||||
end;
|
||||
|
||||
class operator TLatch.Implicit(const A: TLatch): IMycLatch;
|
||||
class operator TLatch.Implicit(const A: TLatch): TLatch.ILatch;
|
||||
begin
|
||||
Result := A.FLatch;
|
||||
end;
|
||||
@@ -423,7 +430,7 @@ end;
|
||||
|
||||
{ TSignal }
|
||||
|
||||
constructor TSignal.Create(const ASignal: IMycSignal);
|
||||
constructor TSignal.Create(const ASignal: ISignal);
|
||||
begin
|
||||
FSignal := ASignal;
|
||||
if not Assigned(FSignal) then
|
||||
@@ -435,17 +442,12 @@ begin
|
||||
Result := TSubscription.Create(FSignal, FSignal.Subscribe(Subscriber));
|
||||
end;
|
||||
|
||||
procedure TSignal.Unsubscribe(Tag: Pointer);
|
||||
begin
|
||||
FSignal.Unsubscribe(Tag);
|
||||
end;
|
||||
|
||||
class operator TSignal.Implicit(const A: TSignal): IMycSignal;
|
||||
class operator TSignal.Implicit(const A: TSignal): ISignal;
|
||||
begin
|
||||
Result := A.FSignal;
|
||||
end;
|
||||
|
||||
class operator TSignal.Implicit(const A: IMycSignal): TSignal;
|
||||
class operator TSignal.Implicit(const A: ISignal): TSignal;
|
||||
begin
|
||||
Result.Create(A);
|
||||
end;
|
||||
|
||||
@@ -9,14 +9,14 @@ uses
|
||||
type
|
||||
IMycTaskManager = interface
|
||||
// TOD Dokumentation
|
||||
function CreateTask(const Gate: TState; const Proc: TProc): TSubscription;
|
||||
function CreateTask(const Gate: TState; const Proc: TProc): TSignal.TSubscription;
|
||||
|
||||
// Waits for the operation associated with State to complete.
|
||||
// Must not be called from a worker thread of this factory.
|
||||
// After waiting, or if the state is already set, any first stored exception
|
||||
// from any worker thread of this factory will be re-raised in the calling (main) thread.
|
||||
// Raises ETaskException if called from within a worker thread.
|
||||
procedure WaitFor(State: IMycState);
|
||||
procedure WaitFor(State: TState.IState);
|
||||
end;
|
||||
|
||||
var
|
||||
@@ -41,8 +41,8 @@ type
|
||||
TMycTaskManagerMock = class(TInterfacedObject, IMycTaskManager)
|
||||
public
|
||||
// IMycTaskManager
|
||||
function CreateTask(const Gate: TState; const Proc: TProc): TSubscription;
|
||||
procedure WaitFor(State: IMycState);
|
||||
function CreateTask(const Gate: TState; const Proc: TProc): TSignal.TSubscription;
|
||||
procedure WaitFor(State: TState.IState);
|
||||
|
||||
constructor Create;
|
||||
end;
|
||||
@@ -72,12 +72,12 @@ begin
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
function TMycTaskManagerMock.CreateTask(const Gate: TState; const Proc: TProc): TSubscription;
|
||||
function TMycTaskManagerMock.CreateTask(const Gate: TState; const Proc: TProc): TSignal.TSubscription;
|
||||
begin
|
||||
Result := Gate.Subscribe(TMycExecMock.Create(Proc));
|
||||
end;
|
||||
|
||||
procedure TMycTaskManagerMock.WaitFor(State: IMycState);
|
||||
procedure TMycTaskManagerMock.WaitFor(State: TState.IState);
|
||||
begin
|
||||
Assert(State.IsSet);
|
||||
end;
|
||||
|
||||
+18
-18
@@ -103,7 +103,7 @@ end;
|
||||
procedure TTestMycCoreLazy.TestNullLazy_GetChanged_IsAlwaysNullState;
|
||||
var
|
||||
nullLazy: IMycLazy<Integer>;
|
||||
changedState: IMycState;
|
||||
changedState: TState.IState;
|
||||
begin
|
||||
nullLazy := TMycNullLazy<Integer>.Create as IMycLazy<Integer>;
|
||||
Assert.IsNotNull(nullLazy, 'TMycNullLazy<Integer> instance should not be nil');
|
||||
@@ -142,12 +142,12 @@ end;
|
||||
|
||||
procedure TTestMycCoreLazy.TestNullLazy_Pop_ReturnsDefaultInterfaceAndTrue;
|
||||
var
|
||||
nullLazy: IMycLazy<IMycState>;
|
||||
value: IMycState;
|
||||
nullLazy: IMycLazy<TState.IState>;
|
||||
value: TState.IState;
|
||||
result: Boolean;
|
||||
begin
|
||||
nullLazy := TMycNullLazy<IMycState>.Create as IMycLazy<IMycState>;
|
||||
Assert.IsNotNull(nullLazy, 'TMycNullLazy<IMycState> instance should not be nil');
|
||||
nullLazy := TMycNullLazy<TState.IState>.Create as IMycLazy<TState.IState>;
|
||||
Assert.IsNotNull(nullLazy, 'TMycNullLazy<TState.IState> instance should not be nil');
|
||||
value := TState.Null;
|
||||
result := nullLazy.Pop(value);
|
||||
Assert.IsTrue(result, 'TMycNullLazy.Pop should return true');
|
||||
@@ -158,15 +158,15 @@ end;
|
||||
procedure TTestMycCoreLazy.TestFuncLazy_GetChanged_IsAlwaysTrueAfterCreation;
|
||||
var
|
||||
funcLazy: IMycLazy<Integer>;
|
||||
changedState: IMycState;
|
||||
sourceDirty: IMycFlag;
|
||||
changedState: TState.IState;
|
||||
sourceDirty: TFlag.IFlag;
|
||||
begin
|
||||
sourceDirty := TFlag.CreateFlag;
|
||||
sourceDirty.Reset;
|
||||
funcLazy := TMycFuncLazy<Integer>.Create(sourceDirty.State, function: Integer begin Result := 10; end);
|
||||
Assert.IsNotNull(funcLazy, 'TMycFuncLazy<Integer> instance should not be nil');
|
||||
changedState := funcLazy.GetChanged;
|
||||
Assert.IsNotNull(changedState, 'funcLazy.GetChanged should return a valid IMycState');
|
||||
Assert.IsNotNull(changedState, 'funcLazy.GetChanged should return a valid TState.IState');
|
||||
Assert.IsTrue(changedState.IsSet, 'By design, funcLazy.GetChanged.IsSet should be true immediately after creation');
|
||||
end;
|
||||
|
||||
@@ -175,7 +175,7 @@ var
|
||||
funcLazy: IMycLazy<Integer>;
|
||||
value: Integer;
|
||||
result: Boolean;
|
||||
sourceDirty: IMycFlag;
|
||||
sourceDirty: TFlag.IFlag;
|
||||
procExecuted: Boolean;
|
||||
expectedValue: Integer;
|
||||
begin
|
||||
@@ -207,7 +207,7 @@ end;
|
||||
procedure TTestMycCoreLazy.TestFuncLazy_AfterFirstPop_IfNoSourceChange_GetChangedIsFalse;
|
||||
var
|
||||
funcLazy: IMycLazy<Integer>;
|
||||
sourceDirty: IMycFlag;
|
||||
sourceDirty: TFlag.IFlag;
|
||||
initialProcValue: Integer;
|
||||
begin
|
||||
sourceDirty := TFlag.CreateFlag;
|
||||
@@ -223,7 +223,7 @@ var
|
||||
funcLazy: IMycLazy<Integer>;
|
||||
value: Integer;
|
||||
result: Boolean;
|
||||
sourceDirty: IMycFlag;
|
||||
sourceDirty: TFlag.IFlag;
|
||||
initialProcValue: Integer;
|
||||
procExecutedCount: Integer;
|
||||
begin
|
||||
@@ -250,8 +250,8 @@ end;
|
||||
procedure TTestMycCoreLazy.TestFuncLazy_AfterSourceChange_GetChanged_IsSet;
|
||||
var
|
||||
funcLazy: IMycLazy<Integer>;
|
||||
changedState: IMycState;
|
||||
sourceDirty: IMycFlag;
|
||||
changedState: TState.IState;
|
||||
sourceDirty: TFlag.IFlag;
|
||||
initialProcValue: Integer;
|
||||
begin
|
||||
sourceDirty := TFlag.CreateFlag;
|
||||
@@ -269,7 +269,7 @@ var
|
||||
funcLazy: IMycLazy<Integer>;
|
||||
value: Integer;
|
||||
result: Boolean;
|
||||
sourceDirty: IMycFlag;
|
||||
sourceDirty: TFlag.IFlag;
|
||||
procCallCount: Integer;
|
||||
currentExpectedValue: Integer;
|
||||
begin
|
||||
@@ -307,7 +307,7 @@ var
|
||||
funcLazy: IMycLazy<Integer>;
|
||||
value: Integer;
|
||||
resultPop1, resultPop2: Boolean;
|
||||
sourceDirty: IMycFlag;
|
||||
sourceDirty: TFlag.IFlag;
|
||||
procCallCount: Integer;
|
||||
begin
|
||||
sourceDirty := TFlag.CreateFlag;
|
||||
@@ -339,7 +339,7 @@ var
|
||||
funcLazy: IMycLazy<Integer>;
|
||||
value: Integer;
|
||||
result: Boolean;
|
||||
sourceDirty: IMycFlag;
|
||||
sourceDirty: TFlag.IFlag;
|
||||
procCallCount: Integer;
|
||||
initialValue, firstSourceChangeValue: Integer;
|
||||
begin
|
||||
@@ -399,7 +399,7 @@ end;
|
||||
procedure TTestMycCoreLazy.TestFuncLazy_Destroy_UnsubscribesFromSource;
|
||||
var
|
||||
funcLazyObj: TMycFuncLazy<Integer>;
|
||||
sourceDirty: IMycFlag;
|
||||
sourceDirty: TFlag.IFlag;
|
||||
tempVal: Integer;
|
||||
begin
|
||||
sourceDirty := TFlag.CreateFlag;
|
||||
@@ -420,7 +420,7 @@ var
|
||||
funcLazy: IMycLazy<Integer>;
|
||||
value: Integer;
|
||||
result: Boolean;
|
||||
sourceDirty: IMycFlag;
|
||||
sourceDirty: TFlag.IFlag;
|
||||
expectedValue: Integer;
|
||||
procExecuted: Boolean;
|
||||
begin
|
||||
|
||||
@@ -12,7 +12,7 @@ type
|
||||
[TestFixture]
|
||||
TTestMyLazy = class(TObject)
|
||||
private
|
||||
FChangingSignal: IMycFlag; // Used as the 'Changing' state for functional lazy objects
|
||||
FChangingSignal: TFlag.IFlag; // Used as the 'Changing' state for functional lazy objects
|
||||
|
||||
// Helper to consume the initial pop, which is always expected to succeed
|
||||
// for a TLazy wrapping a functional lazy object due to "Changed.IsSet initially true" design.
|
||||
@@ -281,7 +281,7 @@ end;
|
||||
procedure TTestMyLazy.TestConstruct_Destruction_UnsubscribesAndNoCrashOnSourceNotify;
|
||||
var
|
||||
lazyIntf: IMycLazy<Integer>;
|
||||
localChangingSignal: IMycFlag; // Use a local signal for this test to control its lifetime
|
||||
localChangingSignal: TFlag.IFlag; // Use a local signal for this test to control its lifetime
|
||||
begin
|
||||
localChangingSignal := TFlag.CreateFlag;
|
||||
localChangingSignal.Reset;
|
||||
|
||||
@@ -24,7 +24,7 @@ type
|
||||
TTestMycDirtyFlag = class(TObject)
|
||||
private
|
||||
// Helper to create a dirty flag and optionally reset it for a clean initial state
|
||||
function CreateAndPrepareDirtyFlag(StartDirty: Boolean = True): IMycFlag;
|
||||
function CreateAndPrepareDirtyFlag(StartDirty: Boolean = True): TFlag.IFlag;
|
||||
public
|
||||
[Setup]
|
||||
procedure Setup;
|
||||
@@ -103,7 +103,7 @@ end;
|
||||
|
||||
{ TTestMycDirtyFlag }
|
||||
|
||||
function TTestMycDirtyFlag.CreateAndPrepareDirtyFlag(StartDirty: Boolean = True): IMycFlag;
|
||||
function TTestMycDirtyFlag.CreateAndPrepareDirtyFlag(StartDirty: Boolean = True): TFlag.IFlag;
|
||||
begin
|
||||
Result := TFlag.CreateFlag; // Initially dirty
|
||||
if not StartDirty then
|
||||
@@ -125,7 +125,7 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestCreate_InitialStateIsDirty;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
begin
|
||||
dirtyFlag := TFlag.CreateFlag;
|
||||
Assert.IsTrue(dirtyFlag.State.IsSet, 'Newly created dirty flag should be IsSet (dirty).');
|
||||
@@ -133,7 +133,7 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestReset_FromDirtyState_BecomesCleanAndReturnsTrue;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
resetResult: Boolean;
|
||||
begin
|
||||
dirtyFlag := CreateAndPrepareDirtyFlag(True); // Start dirty
|
||||
@@ -146,7 +146,7 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestReset_FromCleanState_StaysCleanAndReturnsFalse;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
resetResult: Boolean;
|
||||
begin
|
||||
dirtyFlag := CreateAndPrepareDirtyFlag(False); // Start clean
|
||||
@@ -159,7 +159,7 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestNotify_OnCleanFlag_SetsDirtyAndReturnsTrue;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
notifyResult: Boolean;
|
||||
begin
|
||||
dirtyFlag := CreateAndPrepareDirtyFlag(False); // Start clean
|
||||
@@ -172,7 +172,7 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestNotify_OnDirtyFlag_StaysDirtyAndReturnsFalse;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
notifyResult: Boolean;
|
||||
begin
|
||||
dirtyFlag := CreateAndPrepareDirtyFlag(True); // Start dirty
|
||||
@@ -187,9 +187,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestSubscribe_ToAlreadyDirtyFlag_NotifiesSubscriberImmediately;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
subscriber: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
dirtyFlag := CreateAndPrepareDirtyFlag(True); // Start dirty
|
||||
subscriber := TMockSubscriber.Create;
|
||||
@@ -202,9 +202,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestSubscribe_ToCleanFlag_DoesNotNotifySubscriberImmediately;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
subscriber: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
dirtyFlag := CreateAndPrepareDirtyFlag(False); // Start clean
|
||||
subscriber := TMockSubscriber.Create;
|
||||
@@ -217,9 +217,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestSubscriber_Notified_WhenFlagTransitionsToDirty;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
subscriber: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
dirtyFlag := CreateAndPrepareDirtyFlag(False); // Start clean
|
||||
subscriber := TMockSubscriber.Create;
|
||||
@@ -234,9 +234,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestSubscriber_NotNotified_WhenSettingAlreadyDirtyFlagViaNotify;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
subscriber: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
dirtyFlag := CreateAndPrepareDirtyFlag(True); // Start dirty
|
||||
subscriber := TMockSubscriber.Create;
|
||||
@@ -251,9 +251,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestSubscriber_NotNotified_ByResetAction;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
subscriber: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
dirtyFlag := CreateAndPrepareDirtyFlag(True); // Start dirty
|
||||
subscriber := TMockSubscriber.Create;
|
||||
@@ -269,9 +269,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestMultipleSubscribers_Notified_WhenFlagTransitionsToDirty;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
sub1, sub2: TMockSubscriber;
|
||||
subscription1, subscription2: TSubscription;
|
||||
subscription1, subscription2: TSignal.TSubscription;
|
||||
begin
|
||||
dirtyFlag := CreateAndPrepareDirtyFlag(False); // Start clean
|
||||
sub1 := TMockSubscriber.Create;
|
||||
@@ -287,9 +287,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestUnsubscribe_SubscriberNotNotified;
|
||||
var
|
||||
dirtyFlag: IMycFlag;
|
||||
dirtyFlag: TFlag.IFlag;
|
||||
subscriber: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
dirtyFlag := CreateAndPrepareDirtyFlag(False); // Start clean
|
||||
subscriber := TMockSubscriber.Create;
|
||||
@@ -308,9 +308,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestChain_A_Notifies_B_SimplePropagation;
|
||||
var
|
||||
flagA, flagB: IMycFlag;
|
||||
flagA, flagB: TFlag.IFlag;
|
||||
subToB: TMockSubscriber;
|
||||
subscriptionA_B, subscriptionMock_B: TSubscription;
|
||||
subscriptionA_B, subscriptionMock_B: TSignal.TSubscription;
|
||||
begin
|
||||
flagA := CreateAndPrepareDirtyFlag(False); // A starts clean
|
||||
flagB := CreateAndPrepareDirtyFlag(False); // B starts clean
|
||||
@@ -328,9 +328,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestChain_A_Notifies_B_Notifies_C_SimplePropagation;
|
||||
var
|
||||
flagA, flagB, flagC: IMycFlag;
|
||||
flagA, flagB, flagC: TFlag.IFlag;
|
||||
subToC: TMockSubscriber;
|
||||
subscriptionB_A, subscriptionC_B, subscriptionMock_C: TSubscription;
|
||||
subscriptionB_A, subscriptionC_B, subscriptionMock_C: TSignal.TSubscription;
|
||||
begin
|
||||
flagA := CreateAndPrepareDirtyFlag(False);
|
||||
flagB := CreateAndPrepareDirtyFlag(False);
|
||||
@@ -353,9 +353,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestChain_A_B_ResetB_RetriggerA_BStaysCleanIfANotChanged;
|
||||
var
|
||||
flagA, flagB: IMycFlag;
|
||||
flagA, flagB: TFlag.IFlag;
|
||||
subToB: TMockSubscriber;
|
||||
subscriptionA_B, subscriptionMock_B: TSubscription;
|
||||
subscriptionA_B, subscriptionMock_B: TSignal.TSubscription;
|
||||
begin
|
||||
flagA := CreateAndPrepareDirtyFlag(False);
|
||||
flagB := CreateAndPrepareDirtyFlag(False);
|
||||
@@ -382,9 +382,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestChain_A_B_ResetA_ThenTriggerA_FullPropagationToB;
|
||||
var
|
||||
flagA, flagB: IMycFlag;
|
||||
flagA, flagB: TFlag.IFlag;
|
||||
subToB: TMockSubscriber;
|
||||
subscriptionA_B, subscriptionMock_B: TSubscription;
|
||||
subscriptionA_B, subscriptionMock_B: TSignal.TSubscription;
|
||||
begin
|
||||
flagA := CreateAndPrepareDirtyFlag(False);
|
||||
flagB := CreateAndPrepareDirtyFlag(False);
|
||||
@@ -411,9 +411,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestChain_A_B_C_IntermediateBReset_RetriggerA_PropagatesToC;
|
||||
var
|
||||
flagA, flagB, flagC: IMycFlag;
|
||||
flagA, flagB, flagC: TFlag.IFlag;
|
||||
subToC: TMockSubscriber;
|
||||
subscriptionB_A, subscriptionC_B, subscriptionMock_C: TSubscription;
|
||||
subscriptionB_A, subscriptionC_B, subscriptionMock_C: TSignal.TSubscription;
|
||||
begin
|
||||
flagA := CreateAndPrepareDirtyFlag(False);
|
||||
flagB := CreateAndPrepareDirtyFlag(False);
|
||||
@@ -450,9 +450,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestChain_A_B_C_AllReset_RetriggerA_FullPropagation;
|
||||
var
|
||||
flagA, flagB, flagC: IMycFlag;
|
||||
flagA, flagB, flagC: TFlag.IFlag;
|
||||
subToC: TMockSubscriber;
|
||||
subscriptionB_A, subscriptionC_B, subscriptionMock_C: TSubscription;
|
||||
subscriptionB_A, subscriptionC_B, subscriptionMock_C: TSignal.TSubscription;
|
||||
begin
|
||||
flagA := CreateAndPrepareDirtyFlag(False);
|
||||
flagB := CreateAndPrepareDirtyFlag(False);
|
||||
@@ -490,9 +490,9 @@ end;
|
||||
|
||||
procedure TTestMycDirtyFlag.TestChain_A_B_C_TriggerA_ResetA_TriggerA_EnsureCNotifiedCorrectly;
|
||||
var
|
||||
flagA, flagB, flagC: IMycFlag;
|
||||
flagA, flagB, flagC: TFlag.IFlag;
|
||||
subToC: TMockSubscriber;
|
||||
subscriptionB_A, subscriptionC_B, subscriptionMock_C: TSubscription;
|
||||
subscriptionB_A, subscriptionC_B, subscriptionMock_C: TSignal.TSubscription;
|
||||
begin
|
||||
flagA := CreateAndPrepareDirtyFlag(False);
|
||||
flagB := CreateAndPrepareDirtyFlag(False);
|
||||
|
||||
@@ -120,7 +120,7 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestCreate_InitialState(InitialCount: Integer; ExpectedIsSet: Boolean);
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
begin
|
||||
// TMycLatch.CreateLatch returns TMycLatch.Null if InitialCount <= 0
|
||||
latch := TLatch.CreateLatch(InitialCount);
|
||||
@@ -133,11 +133,11 @@ procedure TTestMycLatch.TestNotify_ReturnValueAndState_AfterOneNotify(
|
||||
ExpectedIsSet: Boolean
|
||||
);
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
returnedValueFromNotify: Boolean;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(InitialCount);
|
||||
returnedValueFromNotify := latch.Notify; // This is IMycLatch (as IMycSubscriber).Notify
|
||||
returnedValueFromNotify := latch.Notify; // This is TLatch.ILatch (as IMycSubscriber).Notify
|
||||
|
||||
Assert.AreEqual(
|
||||
ExpectedReturn,
|
||||
@@ -153,7 +153,7 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestNotify_DecrementsCounter_StateChanges;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(1);
|
||||
Assert.IsFalse(latch.State.IsSet, 'Latch should initially not be set (Count=1).');
|
||||
@@ -163,7 +163,7 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestNotify_MultipleNotifies_CounterBecomesNegativeAndStaysSet;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(1);
|
||||
latch.Notify; // Count becomes 0, IsSet = True
|
||||
@@ -176,9 +176,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestSubscriber_Single_IsNotifiedWhenLatchSet;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
mockSub: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(1);
|
||||
mockSub := TMockSubscriber.Create;
|
||||
@@ -195,9 +195,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestSubscriber_Multiple_AreNotifiedWhenLatchSet;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
mockSub1, mockSub2, mockSub3: TMockSubscriber;
|
||||
sub1, sub2, sub3: TSubscription; // Keep subscriptions in scope
|
||||
sub1, sub2, sub3: TSignal.TSubscription; // Keep subscriptions in scope
|
||||
begin
|
||||
latch := TLatch.CreateLatch(1);
|
||||
mockSub1 := TMockSubscriber.Create;
|
||||
@@ -217,9 +217,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestSubscriber_NotNotified_BeforeLatchSet;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
mockSub: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(2); // Count = 2
|
||||
mockSub := TMockSubscriber.Create;
|
||||
@@ -232,9 +232,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestSubscriber_NotifiedOnlyOnce_AfterLatchSetAndUnadvised;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
mockSub: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(1);
|
||||
mockSub := TMockSubscriber.Create;
|
||||
@@ -249,9 +249,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestSubscribe_ToAlreadySetLatch_NotifiesImmediately;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
mockSub1, mockSub2: TMockSubscriber;
|
||||
subscription1, subscription2: TSubscription;
|
||||
subscription1, subscription2: TSignal.TSubscription;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(1); // Create with count 1
|
||||
mockSub1 := TMockSubscriber.Create;
|
||||
@@ -277,9 +277,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestChaining_A_Notifies_B;
|
||||
var
|
||||
latchA, latchB: IMycLatch;
|
||||
latchA, latchB: TLatch.ILatch;
|
||||
mockSubForB: TMockSubscriber;
|
||||
subHandle_B_listens_A, subHandle_Mock_listens_B: TSubscription;
|
||||
subHandle_B_listens_A, subHandle_Mock_listens_B: TSignal.TSubscription;
|
||||
begin
|
||||
latchA := TLatch.CreateLatch(1);
|
||||
latchB := TLatch.CreateLatch(1); // latchB is an IMycSubscriber
|
||||
@@ -302,9 +302,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestCascade_A_Notifies_B_Notifies_C;
|
||||
var
|
||||
latchA, latchB, latchC: IMycLatch;
|
||||
latchA, latchB, latchC: TLatch.ILatch;
|
||||
mockSubForC: TMockSubscriber;
|
||||
sub_Mock_C, sub_C_B, sub_B_A: TSubscription;
|
||||
sub_Mock_C, sub_C_B, sub_B_A: TSignal.TSubscription;
|
||||
begin
|
||||
latchA := TLatch.CreateLatch(1);
|
||||
latchB := TLatch.CreateLatch(1);
|
||||
@@ -325,9 +325,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestChaining_B_NeedsMultipleNotifiesFromA_WithSubscriberOnB;
|
||||
var
|
||||
latchA, latchB: IMycLatch;
|
||||
latchA, latchB: TLatch.ILatch;
|
||||
mockSubForB: TMockSubscriber;
|
||||
sub_Mock_B, sub_B_A: TSubscription;
|
||||
sub_Mock_B, sub_B_A: TSignal.TSubscription;
|
||||
begin
|
||||
// LatchA needs 2 notifies to become set. LatchB needs 1 notify to become set.
|
||||
// LatchB subscribes to LatchA. So LatchB will be notified once LatchA becomes set.
|
||||
@@ -354,9 +354,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestInitiallySetLatch_NotifiesNewSubscriberImmediately;
|
||||
var
|
||||
latch: IMycLatch; // Will be TMycLatch.Null
|
||||
latch: TLatch.ILatch; // Will be TMycLatch.Null
|
||||
mockSub: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(0); // Returns TMycLatch.Null which is set.
|
||||
mockSub := TMockSubscriber.Create;
|
||||
@@ -369,9 +369,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestUnsubscribe_SubscriberNotNotified;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
mockSub: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(1);
|
||||
mockSub := TMockSubscriber.Create;
|
||||
@@ -388,9 +388,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestMultipleTriggersNoSubscriber_StateCorrectForLaterSubscriber;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
mockSub: TMockSubscriber;
|
||||
subscription: TSubscription;
|
||||
subscription: TSignal.TSubscription;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(3);
|
||||
|
||||
@@ -411,9 +411,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestLatchSet_ClearsSubscribers_NoFurtherNotification;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
mockSub1, mockSub2: TMockSubscriber;
|
||||
subscription1, subscription2: TSubscription;
|
||||
subscription1, subscription2: TSignal.TSubscription;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(1);
|
||||
mockSub1 := TMockSubscriber.Create;
|
||||
@@ -439,7 +439,7 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestLatchSet_SubscriptionFinalize_IsSafePostUnadviseAll;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
mockSub: TMockSubscriber;
|
||||
// 'subscription' will be declared in an inner scope to control its finalization
|
||||
begin
|
||||
@@ -449,7 +449,7 @@ begin
|
||||
var noException: Boolean := True;
|
||||
try
|
||||
begin // Inner block to control lifetime of 'subscription'
|
||||
var subscription: TSubscription; // Local to this block
|
||||
var subscription: TSignal.TSubscription; // Local to this block
|
||||
subscription := latch.State.Subscribe(mockSub);
|
||||
|
||||
latch.Notify; // Sets the latch, mockSub is notified, UnadviseAll is called internally.
|
||||
@@ -475,9 +475,9 @@ end;
|
||||
|
||||
procedure TTestMycLatch.TestLatchSet_NewSubscriberToSetLatch_NotifiedImmediatelyButNotPersistedForLatchNotify;
|
||||
var
|
||||
latch: IMycLatch;
|
||||
latch: TLatch.ILatch;
|
||||
mockSubInitial, mockSubNew: TMockSubscriber;
|
||||
subscriptionInitial, subscriptionNew: TSubscription;
|
||||
subscriptionInitial, subscriptionNew: TSignal.TSubscription;
|
||||
begin
|
||||
latch := TLatch.CreateLatch(1);
|
||||
mockSubInitial := TMockSubscriber.Create;
|
||||
|
||||
+21
-21
@@ -16,9 +16,9 @@ type
|
||||
// Helper class to notify a latch when its Notify method is called.
|
||||
TLatchNotifierSubscriber = class(TInterfacedObject, IMycSubscriber)
|
||||
private
|
||||
FGateLatch: IMycLatch;
|
||||
FGateLatch: TLatch.ILatch;
|
||||
public
|
||||
constructor Create(AGateLatch: IMycLatch);
|
||||
constructor Create(AGateLatch: TLatch.ILatch);
|
||||
// IMycSubscriber
|
||||
function Notify: Boolean; // Implements IMycSubscriber.Notify [cite: 46, 181, 299]
|
||||
end;
|
||||
@@ -54,7 +54,7 @@ implementation
|
||||
|
||||
{ TLatchNotifierSubscriber }
|
||||
|
||||
constructor TLatchNotifierSubscriber.Create(AGateLatch: IMycLatch);
|
||||
constructor TLatchNotifierSubscriber.Create(AGateLatch: TLatch.ILatch);
|
||||
begin
|
||||
inherited Create;
|
||||
FGateLatch := AGateLatch;
|
||||
@@ -89,8 +89,8 @@ end;
|
||||
|
||||
procedure TTestMycGateFuncFuture.Test_BasicSuccess_WithImmediateInitState;
|
||||
var
|
||||
LFuture: IMycFuture<Integer>;
|
||||
LInitStateAsState: IMycState; // Parameter for Create
|
||||
LFuture: TFuture<Integer>.IFuture;
|
||||
LInitStateAsState: TState.IState; // Parameter for Create
|
||||
LResultValue: Integer;
|
||||
const
|
||||
CExpectedResult = 42;
|
||||
@@ -109,19 +109,19 @@ begin
|
||||
end
|
||||
);
|
||||
|
||||
FTaskFactory.WaitFor(LFuture.Done); // Accesses IMycFuture.GetDone [cite: 110, 234, 352]
|
||||
FTaskFactory.WaitFor(LFuture.Done); // Accesses IFuture.GetDone [cite: 110, 234, 352]
|
||||
|
||||
Assert.IsTrue(LFuture.Done.IsSet, 'Future should be marked as done.'); // Accesses IMycState.IsSet [cite: 57, 194, 312]
|
||||
Assert.IsTrue(LFuture.Done.IsSet, 'Future should be marked as done.'); // Accesses TState.IState.IsSet [cite: 57, 194, 312]
|
||||
Assert.AreEqual(1, FProcExecutionCount, 'AProc should have been executed once.');
|
||||
|
||||
LResultValue := LFuture.GetResult; // Accesses IMycFuture.GetResult
|
||||
LResultValue := LFuture.GetResult; // Accesses IFuture.GetResult
|
||||
Assert.AreEqual(CExpectedResult, LResultValue, 'GetResult returned an unexpected value.');
|
||||
end;
|
||||
|
||||
procedure TTestMycGateFuncFuture.Test_ChainedExecution_WithDelayedInitState;
|
||||
var
|
||||
LFuture: IMycFuture<string>;
|
||||
LInitLatch: IMycLatch;
|
||||
LFuture: tFuture<string>.IFuture;
|
||||
LInitLatch: TLatch.ILatch;
|
||||
LResultValue: string;
|
||||
const
|
||||
CExpectedResult = 'ChainCompleted';
|
||||
@@ -155,9 +155,9 @@ end;
|
||||
|
||||
procedure TTestMycGateFuncFuture.Test_ExceptionInProc_HandledAsPlanned;
|
||||
var
|
||||
LFuture: IMycFuture<Integer>;
|
||||
LFuture: TFuture<Integer>.IFuture;
|
||||
LLocalTaskFactory: IMycTaskFactory;
|
||||
LInitStateAsState: IMycState;
|
||||
LInitStateAsState: TState.IState;
|
||||
LResultValue: Integer;
|
||||
LExpectedExceptionRaisedByFactory: Boolean;
|
||||
const
|
||||
@@ -219,8 +219,8 @@ end;
|
||||
|
||||
procedure TTestMycGateFuncFuture.Test_GetResult_BeforeDone_RaisesException;
|
||||
var
|
||||
LFuture: IMycFuture<Integer>;
|
||||
LInitLatch: IMycLatch;
|
||||
LFuture: TFuture<Integer>.IFuture;
|
||||
LInitLatch: TLatch.ILatch;
|
||||
begin
|
||||
LInitLatch := TLatch.CreateLatch(1);
|
||||
|
||||
@@ -248,12 +248,12 @@ end;
|
||||
|
||||
procedure TTestMycGateFuncFuture.Test_FanIn_OneFutureWaitsForMultipleOthers;
|
||||
var
|
||||
LPrerequisiteFuture1, LPrerequisiteFuture2: IMycFuture<Integer>;
|
||||
LMainFuture: IMycFuture<string>;
|
||||
LGateLatch: IMycLatch;
|
||||
LPrerequisiteFuture1, LPrerequisiteFuture2: TFuture<Integer>.IFuture;
|
||||
LMainFuture: TFuture<string>.IFuture;
|
||||
LGateLatch: TLatch.ILatch;
|
||||
LSub1, LSub2: IMycSubscriber; // To hold the TLatchNotifierSubscriber instances
|
||||
LInitStateP1, LInitStateP2: IMycLatch;
|
||||
Subscriptions: array[1..2] of TSubscription; // To manage subscriptions
|
||||
LInitStateP1, LInitStateP2: TLatch.ILatch;
|
||||
Subscriptions: array[1..2] of TSignal.TSubscription; // To manage subscriptions
|
||||
const
|
||||
CMainFutureResult = 'AllPrerequisitesCompleted';
|
||||
begin
|
||||
@@ -335,8 +335,8 @@ end;
|
||||
|
||||
procedure TTestMycGateFuncFuture.Test_FanOut_MultipleFuturesWaitForOneTrigger;
|
||||
var
|
||||
LTriggerLatch: IMycLatch;
|
||||
LFutureA, LFutureB: IMycFuture<Integer>;
|
||||
LTriggerLatch: TLatch.ILatch;
|
||||
LFutureA, LFutureB: TFuture<Integer>.IFuture;
|
||||
LFlagFutureARan, LFlagFutureBRan: Boolean;
|
||||
begin
|
||||
LFlagFutureARan := False;
|
||||
|
||||
@@ -120,10 +120,10 @@ end;
|
||||
procedure TTestFuture.TestConstructWithPresetGate;
|
||||
var
|
||||
fut: TFuture<Integer>;
|
||||
presetGate: IMycState;
|
||||
presetGate: TState.IState;
|
||||
resultValue: Integer;
|
||||
begin
|
||||
presetGate := TState.Null; // State.Null is an IMycState that is always set [cite: 68]
|
||||
presetGate := TState.Null; // State.Null is an TState.IState that is always set [cite: 68]
|
||||
Assert.IsTrue(presetGate.IsSet, 'The preset gate (State.Null) should be initially set.'); // Static string [cite: 55]
|
||||
|
||||
// Construct a future with a gate that is already set
|
||||
@@ -148,17 +148,17 @@ end;
|
||||
procedure TTestFuture.TestConstructWithDelayedGate;
|
||||
var
|
||||
fut: TFuture<Integer>;
|
||||
delayedGate: IMycLatch; // IMycLatch implements IMycState [cite: 58]
|
||||
delayedGate: TLatch.ILatch; // TLatch.ILatch implements TState.IState [cite: 58]
|
||||
resultValue: Integer;
|
||||
begin
|
||||
delayedGate := TLatch.CreateLatch(1); // Create a latch that requires one notification to be set [cite: 66]
|
||||
Assert.IsNotNull(delayedGate, 'The delayed gate (IMycLatch) should not be nil.'); // Static string
|
||||
Assert.IsNotNull(delayedGate, 'The delayed gate (TLatch.ILatch) should not be nil.'); // Static string
|
||||
Assert.IsFalse(delayedGate.State.IsSet, 'The delayed gate should not be initially set.'); // Static string [cite: 59, 55]
|
||||
|
||||
// Construct a future with a gate that is not yet set
|
||||
fut :=
|
||||
TFuture<Integer>.Construct(
|
||||
delayedGate.State, // Get the IMycState interface from the latch [cite: 147, 59]
|
||||
delayedGate.State, // Get the TState.IState interface from the latch [cite: 147, 59]
|
||||
function: Integer begin Result := 45; end
|
||||
);
|
||||
|
||||
@@ -220,7 +220,7 @@ procedure TTestFuture.TestChainWithGate;
|
||||
var
|
||||
fut1: TFuture<Integer>;
|
||||
fut2: TFuture<string>;
|
||||
delayedGate: IMycLatch;
|
||||
delayedGate: TLatch.ILatch;
|
||||
resultValue: string;
|
||||
begin
|
||||
delayedGate := TLatch.CreateLatch(1); // [cite: 66]
|
||||
@@ -341,7 +341,7 @@ const
|
||||
var
|
||||
Futures: TArray<TFuture<Integer>>;
|
||||
doneStates: TArray<TState>;
|
||||
combinedStateAll: IMycState;
|
||||
combinedStateAll: TState.IState;
|
||||
masterFuture: TFuture<Boolean>;
|
||||
i: Integer;
|
||||
begin
|
||||
@@ -374,7 +374,7 @@ begin
|
||||
end;
|
||||
|
||||
combinedStateAll := TState.All(doneStates); // [cite: 67]
|
||||
Assert.IsNotNull(combinedStateAll, 'State.All should return a valid IMycState.'); // Static string
|
||||
Assert.IsNotNull(combinedStateAll, 'State.All should return a valid TState.IState.'); // Static string
|
||||
|
||||
// Create a master future that waits on the combined State.All state
|
||||
masterFuture :=
|
||||
@@ -447,7 +447,7 @@ begin
|
||||
end;
|
||||
|
||||
combinedStateAny := TState.Any(doneStates); // [cite: 68]
|
||||
Assert.IsNotNull(combinedStateAny, 'State.Any should return a valid IMycState.'); // Static string
|
||||
Assert.IsNotNull(combinedStateAny, 'State.Any should return a valid TState.IState.'); // Static string
|
||||
|
||||
// Create a master future that waits on the combined State.Any state
|
||||
masterFuture :=
|
||||
|
||||
+8
-8
@@ -70,7 +70,7 @@ end;
|
||||
procedure TMycTaskFactoryTests.TestCreateThreadExecutesAndSignals;
|
||||
var
|
||||
executed: Boolean;
|
||||
threadState: IMycState;
|
||||
threadState: TState.IState;
|
||||
procWrapper: TProc;
|
||||
begin
|
||||
executed := False;
|
||||
@@ -86,7 +86,7 @@ end;
|
||||
procedure TMycTaskFactoryTests.TestRunImmediateJob;
|
||||
var
|
||||
jobExecuted: Boolean;
|
||||
jobCompletedLatch: IMycLatch;
|
||||
jobCompletedLatch: TLatch.ILatch;
|
||||
begin
|
||||
jobExecuted := False;
|
||||
jobCompletedLatch := TLatch.CreateLatch(1); // Changed from Signals.CreateLatch
|
||||
@@ -107,7 +107,7 @@ end;
|
||||
procedure TMycTaskFactoryTests.TestRunDelayedJobExecutesAfterAllNotifies;
|
||||
var
|
||||
jobExecuted: Boolean;
|
||||
jobCompletedLatch: IMycLatch;
|
||||
jobCompletedLatch: TLatch.ILatch;
|
||||
subscriber: IMycSubscriber;
|
||||
begin
|
||||
jobExecuted := False;
|
||||
@@ -134,7 +134,7 @@ end;
|
||||
|
||||
procedure TMycTaskFactoryTests.TestWaitForAlreadySetState;
|
||||
var
|
||||
alreadySetLatch: IMycLatch;
|
||||
alreadySetLatch: TLatch.ILatch;
|
||||
startTime, endTime: Cardinal;
|
||||
begin
|
||||
// TMycLatch.CreateLatch(0) will return TMycLatch.Null
|
||||
@@ -152,7 +152,7 @@ procedure TMycTaskFactoryTests.TestThreadInfoMethods;
|
||||
var
|
||||
inMainThreadInJob: Boolean;
|
||||
inWorkerThreadInJob: Boolean;
|
||||
jobDoneLatch: IMycLatch;
|
||||
jobDoneLatch: TLatch.ILatch;
|
||||
begin
|
||||
inMainThreadInJob := True;
|
||||
inWorkerThreadInJob := False;
|
||||
@@ -178,7 +178,7 @@ end;
|
||||
|
||||
procedure TMycTaskFactoryTests.TestExceptionPropagationFromJob;
|
||||
var
|
||||
jobDoneLatch: IMycLatch;
|
||||
jobDoneLatch: TLatch.ILatch;
|
||||
begin
|
||||
jobDoneLatch := TLatch.CreateLatch(1);
|
||||
|
||||
@@ -222,8 +222,8 @@ end;
|
||||
procedure TMycTaskFactoryTests.TestWaitForInWorkerThreadRaisesException;
|
||||
var
|
||||
exceptionCaughtInJob: Boolean;
|
||||
jobDoneLatch: IMycLatch;
|
||||
dummyStateToWaitFor: IMycState;
|
||||
jobDoneLatch: TLatch.ILatch;
|
||||
dummyStateToWaitFor: TState.IState;
|
||||
begin
|
||||
exceptionCaughtInJob := False;
|
||||
jobDoneLatch := TLatch.CreateLatch(1);
|
||||
|
||||
Reference in New Issue
Block a user