DataPoint

This commit is contained in:
Michael Schimmel
2025-06-24 08:11:46 +02:00
parent 6c7cc2569b
commit a3da63ad6a
14 changed files with 902 additions and 633 deletions
+95 -20
View File
@@ -13,15 +13,18 @@ type
TMycNullSignal = class(TInterfacedObject, TSignal.ISignal)
public
function Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
procedure Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
procedure Unsubscribe(Tag: Pointer);
end;
// TMycNullState implements a "null object" pattern for IMycState.
// This state is always considered "set".
TMycNullState = class(TMycNullSignal, TState.IState)
TMycNullState = class(TInterfacedObject, TSignal.ISignal, TState.IState)
protected
// TState.IState
function GetIsSet: Boolean;
public
function Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
procedure Unsubscribe(Tag: Pointer);
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.
@@ -35,7 +38,7 @@ type
constructor Create;
destructor Destroy; override;
function Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
procedure Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
procedure Unsubscribe(Tag: Pointer);
function Notify: Boolean;
end;
@@ -45,6 +48,16 @@ type
function Notify: Boolean;
end;
TMycRouterEvent = class(TMycEvent)
private
FSignal: TSignal.ISignal;
FSubscriptionTag: TSignal.TSubscriptionTag;
public
constructor Create(const ASignal: TSignal.ISignal);
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
end;
// TMycLatch implements a countdown latch.
// It is initialized with a count. Calls to its Notify method (as an TSignal.ISubscriber)
// decrement this count. When the count reaches zero, the latch transitions to the "set"
@@ -66,7 +79,7 @@ type
// ISignal implementation
function Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
procedure Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
procedure Unsubscribe(Tag: Pointer);
// TSignal.ISubscriber implementation for TMycLatch itself.
// Decrements the internal count. If the count reaches zero,
@@ -101,7 +114,7 @@ type
class function CreateDirty: TFlag.IFlag; static;
function Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
procedure Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
procedure Unsubscribe(Tag: Pointer);
// TSignal.ISubscriber implementation for TMycFlag.
// Sets this flag to dirty (true). Notifies subscribers if it transitioned from clean to dirty.
@@ -118,16 +131,54 @@ type
function Reset: Boolean;
end;
TMycObserverFlag = class(TMycFlag)
private
FSignal: TSignal.ISignal;
FSubscriptionTag: TSignal.TSubscriptionTag;
public
constructor Create(const ASignal: TSignal.ISignal);
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
end;
implementation
uses
System.SyncObjs; // For TInterlocked
{ TMycNullSignal }
function TMycNullSignal.Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
begin
// No ongoing subscription is necessary or meaningful for a null state.
Result := nil;
end;
procedure TMycNullSignal.Unsubscribe(Tag: Pointer);
begin
// Unsubscribing from a null signal has no effect.
end;
{ TMycNullState }
function TMycNullState.GetIsSet: Boolean;
begin
Result := true; // Null state is always set.
end;
function TMycNullState.Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
begin
// Since the state is always set, notify the subscriber immediately.
if Assigned(Subscriber) then
Subscriber.Notify;
Result := nil;
end;
procedure TMycNullState.Unsubscribe(Tag: Pointer);
begin
// Unsubscribing from a null state has no effect.
end;
{ TMycEvent }
constructor TMycEvent.Create;
@@ -178,7 +229,7 @@ begin
end;
end;
procedure TMycEvent.Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
procedure TMycEvent.Unsubscribe(Tag: Pointer);
begin
if Tag = nil then
exit;
@@ -191,6 +242,26 @@ begin
end;
end;
{ TMycRouterEvent }
constructor TMycRouterEvent.Create(const ASignal: TSignal.ISignal);
begin
inherited Create;
FSignal := ASignal;
end;
procedure TMycRouterEvent.AfterConstruction;
begin
inherited;
FSubscriptionTag := FSignal.Subscribe(Self);
end;
procedure TMycRouterEvent.BeforeDestruction;
begin
FSignal.Unsubscribe(FSubscriptionTag);
inherited;
end;
{ TMycNullLatch }
function TMycNullLatch.GetState: TState;
@@ -289,7 +360,7 @@ begin
end;
end;
procedure TMycLatch.Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
procedure TMycLatch.Unsubscribe(Tag: Pointer);
begin
if Tag = nil then
exit;
@@ -324,7 +395,7 @@ end;
constructor TMycFlag.Create;
begin
inherited Create;
FFlag := true; // A new dirty flag is initially considered dirty.
FFlag := false;
FSubscribers.Create;
end;
@@ -371,9 +442,9 @@ begin
begin
FSubscribers.Notify(function(Subscriber: TSignal.ISubscriber): Boolean begin Result := Subscriber.Notify; end);
end;
Result := true;
finally
FSubscribers.Release;
Result := true;
end;
end;
@@ -399,7 +470,7 @@ begin
end;
end;
procedure TMycFlag.Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
procedure TMycFlag.Unsubscribe(Tag: Pointer);
begin
if Tag = nil then
exit;
@@ -422,20 +493,24 @@ begin
Result := false;
end;
function TMycNullSignal.Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
{ TMycObserverFlag }
constructor TMycObserverFlag.Create(const ASignal: TSignal.ISignal);
begin
// Since the state is always set, notify the subscriber immediately.
if Assigned(Subscriber) then
begin
Subscriber.Notify;
end;
// No ongoing subscription is necessary or meaningful for a null state.
Result := nil;
inherited Create;
FSignal := ASignal;
end;
procedure TMycNullSignal.Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
procedure TMycObserverFlag.AfterConstruction;
begin
// Unsubscribing from a null state has no effect.
inherited;
FSubscriptionTag := FSignal.Subscribe(Self);
end;
procedure TMycObserverFlag.BeforeDestruction;
begin
FSignal.Unsubscribe(FSubscriptionTag);
inherited;
end;
end.