Implemented TLazy + Tests

This commit is contained in:
Michael Schimmel
2025-06-03 17:10:55 +02:00
parent 38c9e2830d
commit 254eb7b114
18 changed files with 1329 additions and 149 deletions
+41 -36
View File
@@ -9,18 +9,12 @@ uses
type
TMycState = class abstract( TInterfacedObject, IMycState )
strict private
class var
FNull: IMycState;
class constructor ClassCreate;
protected
function GetIsSet: Boolean; virtual; abstract;
public
function Subscribe(Subscriber: IMycSubscriber): TMycSubscription; virtual; abstract;
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag); virtual; abstract;
property IsSet: Boolean read GetIsSet;
// Provides access to the singleton null latch instance (always set).
class property Null: IMycState read FNull;
end;
// TMycNullState implements a "null object" pattern for IMycState.
@@ -42,9 +36,6 @@ type
TMycLatch = class(TMycState, IMycLatch)
strict private
FSubscribers: TMycNotifyList<IMycSubscriber>; // List of subscribers waiting for this latch to be set.
class var
FNull: IMycLatch; // Singleton instance of a latch that is always set.
class constructor ClassCreate; // Class constructor to initialize FNull.
private
[volatile] FCount: Integer; // The internal countdown value for the latch.
function GetState: IMycState; // Implementation for IMycLatch.GetState and IMycFlag.GetState.
@@ -56,9 +47,6 @@ type
constructor Create(ACount: Integer);
destructor Destroy; override;
// Factory method: creates a new countdown latch or returns the Null latch if Count <= 0.
class function CreateLatch(Count: Integer): IMycLatch; static;
// IMycSignal implementation
function Subscribe(Subscriber: IMycSubscriber): TMycSubscription; override;
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag); override;
@@ -67,9 +55,12 @@ type
// Decrements the internal count. If the count reaches zero,
// registered subscribers are notified, and the latch becomes permanently set.
function Notify: Boolean;
end;
// Provides access to the singleton null latch instance (always set).
class property Null: IMycLatch read FNull;
TMycNullLatch = class( TInterfacedObject, IMycLatch )
private
function GetState: IMycState;
function Notify: Boolean;
end;
// TMycDirty implements a resettable "dirty flag".
@@ -91,7 +82,6 @@ type
// Factory method to create a new TMycDirty instance.
class function CreateDirty: IMycDirty; static;
// IMycSignal implementation
function Subscribe(Subscriber: IMycSubscriber): TMycSubscription; override;
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag); override;
@@ -103,17 +93,18 @@ type
function Reset: Boolean;
end;
TMycNullDirty = class( TInterfacedObject, IMycDirty )
private
function GetState: IMycState;
function Notify: Boolean;
function Reset: Boolean;
end;
implementation
uses
System.SyncObjs; // For TInterlocked
class constructor TMycState.ClassCreate;
begin
// Create a singleton null latch instance that is initially (and always) set.
FNull := TMycNullState.Create(); // Calls the instance constructor
end;
{ TMycNullState }
constructor TMycNullState.Create;
@@ -142,6 +133,18 @@ begin
// Unsubscribing from a null state has no effect.
end;
{ TMycNullLatch }
function TMycNullLatch.GetState: IMycState;
begin
Result := TState.Null;
end;
function TMycNullLatch.Notify: Boolean;
begin
Result := false;
end;
{ TMycLatch }
constructor TMycLatch.Create(ACount: Integer);
@@ -152,27 +155,12 @@ begin
FSubscribers.Create;
end;
class constructor TMycLatch.ClassCreate;
begin
// Create a singleton null latch instance that is initially (and always) set.
FNull := TMycLatch.Create(0); // Calls the instance constructor
end;
destructor TMycLatch.Destroy;
begin
FSubscribers.Destroy;
inherited;
end;
class function TMycLatch.CreateLatch(Count: Integer): IMycLatch;
begin
// Factory method: returns a new latch or the shared Null latch if Count <= 0.
if Count > 0 then
Result := TMycLatch.Create(Count) // Instance constructor
else
Result := FNull;
end;
function TMycLatch.Notify: Boolean;
var
currentCountAfterDecrement: Integer;
@@ -259,6 +247,23 @@ begin
end;
end;
{ TMycNullDirty }
function TMycNullDirty.GetState: IMycState;
begin
Result := TState.Null;
end;
function TMycNullDirty.Notify: Boolean;
begin
Result := false;
end;
function TMycNullDirty.Reset: Boolean;
begin
Result := true;
end;
{ TMycDirty }
constructor TMycDirty.Create;