TMutable
This commit is contained in:
+44
-31
@@ -12,8 +12,8 @@ type
|
||||
// This state is always considered "set".
|
||||
TMycNullSignal = class(TInterfacedObject, TSignal.ISignal)
|
||||
public
|
||||
function Subscribe(Subscriber: IMycSubscriber): Pointer;
|
||||
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
|
||||
function Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
|
||||
procedure Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
|
||||
end;
|
||||
|
||||
// TMycNullState implements a "null object" pattern for IMycState.
|
||||
@@ -27,29 +27,31 @@ type
|
||||
// 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.ISignal, TEvent.IEvent)
|
||||
strict private
|
||||
FSubscribers: TMycNotifyList<IMycSubscriber>;
|
||||
FSubscribers: TMycNotifyList<TSignal.ISubscriber>;
|
||||
protected
|
||||
function GetSignal: TSignal;
|
||||
function GetIsSet: Boolean;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
function Subscribe(Subscriber: IMycSubscriber): Pointer;
|
||||
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
|
||||
procedure Trigger;
|
||||
function Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
|
||||
procedure Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
|
||||
function Notify: Boolean;
|
||||
end;
|
||||
|
||||
TMycNullEvent = class(TMycNullSignal, TEvent.IEvent)
|
||||
private
|
||||
procedure Trigger;
|
||||
function GetSignal: TSignal;
|
||||
function Notify: Boolean;
|
||||
end;
|
||||
|
||||
// TMycLatch implements a countdown latch.
|
||||
// It is initialized with a count. Calls to its Notify method (as an IMycSubscriber)
|
||||
// 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"
|
||||
// state (IsSet becomes true), notifies its current subscribers once, and then remains set.
|
||||
TMycLatch = class(TInterfacedObject, TState.IState, TLatch.ILatch)
|
||||
strict private
|
||||
FSubscribers: TMycNotifyList<IMycSubscriber>; // List of subscribers waiting for this latch to be set.
|
||||
FSubscribers: TMycNotifyList<TSignal.ISubscriber>; // List of subscribers waiting for this latch to be set.
|
||||
private
|
||||
[volatile]
|
||||
FCount: Integer; // The internal countdown value for the latch.
|
||||
@@ -63,10 +65,10 @@ type
|
||||
destructor Destroy; override;
|
||||
|
||||
// ISignal implementation
|
||||
function Subscribe(Subscriber: IMycSubscriber): Pointer;
|
||||
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
|
||||
function Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
|
||||
procedure Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
|
||||
|
||||
// IMycSubscriber implementation for TMycLatch itself.
|
||||
// TSignal.ISubscriber implementation for TMycLatch itself.
|
||||
// Decrements the internal count. If the count reaches zero,
|
||||
// registered subscribers are notified, and the latch becomes permanently set.
|
||||
function Notify: Boolean;
|
||||
@@ -83,7 +85,7 @@ type
|
||||
// Subscribers are notified of relevant state changes.
|
||||
TMycFlag = class(TInterfacedObject, TState.IState, TFlag.IFlag)
|
||||
strict private
|
||||
FSubscribers: TMycNotifyList<IMycSubscriber>; // List of subscribers interested in state changes of this dirty flag.
|
||||
FSubscribers: TMycNotifyList<TSignal.ISubscriber>; // List of subscribers interested in state changes of this dirty flag.
|
||||
private
|
||||
[volatile]
|
||||
FFlag: Boolean; // Internal state: true if dirty/set, false if clean/reset.
|
||||
@@ -98,10 +100,10 @@ type
|
||||
// Factory method to create a new TMycFlag instance.
|
||||
class function CreateDirty: TFlag.IFlag; static;
|
||||
|
||||
function Subscribe(Subscriber: IMycSubscriber): Pointer;
|
||||
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
|
||||
function Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
|
||||
procedure Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
|
||||
|
||||
// IMycSubscriber implementation for TMycFlag.
|
||||
// TSignal.ISubscriber implementation for TMycFlag.
|
||||
// Sets this flag to dirty (true). Notifies subscribers if it transitioned from clean to dirty.
|
||||
function Notify: Boolean;
|
||||
|
||||
@@ -145,17 +147,23 @@ begin
|
||||
Result := true;
|
||||
end;
|
||||
|
||||
procedure TMycEvent.Trigger;
|
||||
function TMycEvent.GetSignal: TSignal;
|
||||
begin
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TMycEvent.Notify: Boolean;
|
||||
begin
|
||||
FSubscribers.Lock;
|
||||
try
|
||||
FSubscribers.Notify(function(Subscriber: IMycSubscriber): Boolean begin Result := Subscriber.Notify; end);
|
||||
FSubscribers.Notify(function(Subscriber: TSignal.ISubscriber): Boolean begin Result := Subscriber.Notify; end);
|
||||
finally
|
||||
FSubscribers.Release;
|
||||
end;
|
||||
Result := true;
|
||||
end;
|
||||
|
||||
function TMycEvent.Subscribe(Subscriber: IMycSubscriber): Pointer;
|
||||
function TMycEvent.Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
|
||||
begin
|
||||
Result := nil;
|
||||
if not Assigned(Subscriber) then
|
||||
@@ -170,7 +178,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMycEvent.Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
|
||||
procedure TMycEvent.Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
|
||||
begin
|
||||
if Tag = nil then
|
||||
exit;
|
||||
@@ -227,7 +235,7 @@ begin
|
||||
|
||||
if shouldNotifySubscribers then
|
||||
begin
|
||||
FSubscribers.Notify(function(Subscriber: IMycSubscriber): Boolean begin Result := Subscriber.Notify; end);
|
||||
FSubscribers.Notify(function(Subscriber: TSignal.ISubscriber): Boolean begin Result := Subscriber.Notify; end);
|
||||
end;
|
||||
|
||||
// Returns true if the latch has not yet been set by this Notify call (count > 0).
|
||||
@@ -254,7 +262,7 @@ begin
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TMycLatch.Subscribe(Subscriber: IMycSubscriber): Pointer;
|
||||
function TMycLatch.Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
|
||||
var
|
||||
alreadySet: Boolean;
|
||||
begin
|
||||
@@ -281,7 +289,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMycLatch.Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
|
||||
procedure TMycLatch.Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
|
||||
begin
|
||||
if Tag = nil then
|
||||
exit;
|
||||
@@ -361,9 +369,9 @@ begin
|
||||
|
||||
if wasPreviouslyClean then // Only notify subscribers if state changed from clean to dirty.
|
||||
begin
|
||||
FSubscribers.Notify(function(Subscriber: IMycSubscriber): Boolean begin Result := Subscriber.Notify; end);
|
||||
FSubscribers.Notify(function(Subscriber: TSignal.ISubscriber): Boolean begin Result := Subscriber.Notify; end);
|
||||
end;
|
||||
// The return value of this Notify (as an IMycSubscriber) indicates if this
|
||||
// The return value of this Notify (as an TSignal.ISubscriber) indicates if this
|
||||
// TMycFlag instance itself would want more notifications if it were subscribed to something.
|
||||
// Here, it reflects whether a state change to dirty occurred due to this call.
|
||||
Result := wasPreviouslyClean;
|
||||
@@ -372,7 +380,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TMycFlag.Subscribe(Subscriber: IMycSubscriber): Pointer;
|
||||
function TMycFlag.Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
|
||||
begin
|
||||
if not Assigned(Subscriber) then
|
||||
exit(nil);
|
||||
@@ -394,7 +402,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMycFlag.Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
|
||||
procedure TMycFlag.Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
|
||||
begin
|
||||
if Tag = nil then
|
||||
exit;
|
||||
@@ -407,12 +415,17 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMycNullEvent.Trigger;
|
||||
function TMycNullEvent.GetSignal: TSignal;
|
||||
begin
|
||||
// nop
|
||||
Result := TSignal.Null;
|
||||
end;
|
||||
|
||||
function TMycNullSignal.Subscribe(Subscriber: IMycSubscriber): Pointer;
|
||||
function TMycNullEvent.Notify: Boolean;
|
||||
begin
|
||||
Result := false;
|
||||
end;
|
||||
|
||||
function TMycNullSignal.Subscribe(Subscriber: TSignal.ISubscriber): Pointer;
|
||||
begin
|
||||
// Since the state is always set, notify the subscriber immediately.
|
||||
if Assigned(Subscriber) then
|
||||
@@ -423,7 +436,7 @@ begin
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
procedure TMycNullSignal.Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
|
||||
procedure TMycNullSignal.Unsubscribe(Tag: TMycNotifyList<TSignal.ISubscriber>.TTag);
|
||||
begin
|
||||
// Unsubscribing from a null state has no effect.
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user