TaskFactory added

This commit is contained in:
Michael Schimmel
2025-05-26 00:27:09 +02:00
parent 10ef4cbcf2
commit 95fddb0181
13 changed files with 1292 additions and 251 deletions
+84 -73
View File
@@ -20,11 +20,12 @@ type
FSignal: TMycSignal;
FTag: TMycNotifyList<IMycSubscriber>.TTag;
public
procedure Setup(ASignal: TMycSignal; ATag: TMycNotifyList<IMycSubscriber>.TTag); inline;
class operator Assign(var Dest: TMycSubscription; const [ref] Src:
TMycSubscription);
class operator Initialize(out Dest: TMycSubscription);
class operator Finalize(var Dest: TMycSubscription);
class operator Assign(var Dest: TMycSubscription; const [ref] Src: TMycSubscription);
procedure Setup(ASignal: TMycSignal; ATag: TMycNotifyList<IMycSubscriber>.TTag); inline;
procedure Unsubscribe;
end;
IMycSignal = interface
@@ -32,18 +33,9 @@ type
end;
TMycSignal = class abstract( TInterfacedObject, IMycSignal )
strict private
FSubscribers: TMycNotifyList<IMycSubscriber>;
private
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
protected
procedure Lock;
procedure Unlock;
procedure Finalize;
procedure Notify;
public
function Subscribe(const Subscriber: IMycSubscriber): TMycSubscription;
property Subscribers: TMycNotifyList<IMycSubscriber> read FSubscribers;
function Subscribe(const Subscriber: IMycSubscriber): TMycSubscription; virtual; abstract;
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag); virtual; abstract;
end;
IMycState = interface( IMycSignal )
@@ -61,18 +53,28 @@ type
end;
TMycSemaphore = class(TMycSignal, IMycSemaphore, IMycState)
strict private
FSubscribers: TMycNotifyList<IMycSubscriber>;
private
[volatile] FCount: Integer;
function GetState: IMycState;
function GetIsSet: Boolean;
protected
function Notify: Boolean;
public
constructor Create(ACount: Integer);
destructor Destroy; override;
function Subscribe(const Subscriber: IMycSubscriber): TMycSubscription; override;
procedure Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag); override;
function Notify: Boolean;
end;
Signals = record
strict private
class var
FNull: IMycSemaphore;
class constructor Create;
public
class function CreateSemaphore(Count: Integer): IMycSemaphore; static;
class property Null: IMycSemaphore read FNull;
end;
implementation
@@ -80,63 +82,23 @@ implementation
uses
System.SyncObjs;
procedure TMycSignal.Finalize;
begin
FSubscribers.Finalize;
end;
procedure TMycSignal.Lock;
begin
FSubscribers.Lock;
end;
procedure TMycSignal.Notify;
begin
FSubscribers.Notify(
function( Subscriber: IMycSubscriber ): Boolean
begin
Result := Subscriber.Notify;
end );
end;
function TMycSignal.Subscribe(const Subscriber: IMycSubscriber): TMycSubscription;
begin
if not Assigned(Subscriber) then
exit;
FSubscribers.Lock;
try
Result.Setup( Self, FSubscribers.Advise( Subscriber ) );
finally
FSubscribers.Release;
end;
end;
procedure TMycSignal.Unlock;
begin
end;
procedure TMycSignal.Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
begin
if Tag=nil then
exit;
FSubscribers.Lock;
try
FSubscribers.Unadvise( Tag );
finally
FSubscribers.Release;
end;
end;
procedure TMycSubscription.Setup(ASignal: TMycSignal; ATag:
TMycNotifyList<IMycSubscriber>.TTag);
begin
Unsubscribe;
FSignal := ASignal;
FTag := ATag;
end;
procedure TMycSubscription.Unsubscribe;
begin
if FTag<>nil then
begin
FSignal.Unsubscribe( FTag );
FTag := nil;
end;
end;
class operator TMycSubscription.Assign(var Dest: TMycSubscription; const [ref]
Src: TMycSubscription);
begin
@@ -150,33 +112,42 @@ end;
class operator TMycSubscription.Finalize(var Dest: TMycSubscription);
begin
if Dest.FTag=nil then
exit;
Dest.FSignal.Unsubscribe( Dest.FTag );
Dest.Unsubscribe;
end;
constructor TMycSemaphore.Create(ACount: Integer);
begin
inherited Create;
FCount := ACount;
FSubscribers.Create;
end;
destructor TMycSemaphore.Destroy;
begin
FSubscribers.Destroy;
inherited;
end;
function TMycSemaphore.Notify: Boolean;
begin
Lock;
FSubscribers.Lock;
try
var n := TInterlocked.Decrement( FCount );
if n < -MaxInt div 2 then
TInterlocked.Increment( FCount );
if n = 0 then
Notify;
FSubscribers.Notify(
function( Subscriber: IMycSubscriber ): Boolean
begin
Result := Subscriber.Notify;
end );
Result := n > 0;
if not Result then
Finalize;
FSubscribers.UnadviseAll;
finally
Release;
FSubscribers.Release;
end;
end;
@@ -190,6 +161,46 @@ begin
exit( Self );
end;
function TMycSemaphore.Subscribe(const Subscriber: IMycSubscriber):
TMycSubscription;
begin
if not Assigned(Subscriber) then
exit;
Subscriber._AddRef;
try
FSubscribers.Lock;
try
if FCount <= 0 then
Subscriber.Notify
else
Result.Setup( Self, FSubscribers.Advise( Subscriber ) );
finally
FSubscribers.Release;
end;
finally
Subscriber._Release;
end;
end;
procedure TMycSemaphore.Unsubscribe(Tag: TMycNotifyList<IMycSubscriber>.TTag);
begin
if Tag=nil then
exit;
FSubscribers.Lock;
try
FSubscribers.Unadvise( Tag );
finally
FSubscribers.Release;
end;
end;
class constructor Signals.Create;
begin
FNull := TMycSemaphore.Create( 0 );
end;
{ Signals }
class function Signals.CreateSemaphore(Count: Integer): IMycSemaphore;