TaskFactory added
This commit is contained in:
+84
-73
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user