lazcollections: TLazThreadedQueue, allow subclasses to Lock/Unlock and access queue.

git-svn-id: trunk@63827 -
This commit is contained in:
martin 2020-08-25 17:31:49 +00:00
parent 3c6130a277
commit 005fe7208d

View File

@ -38,6 +38,8 @@ type
{ TThreadedQueue } { TThreadedQueue }
{ TLazThreadedQueue }
generic TLazThreadedQueue<T> = class generic TLazThreadedQueue<T> = class
private private
FMonitor: TLazMonitor; FMonitor: TLazMonitor;
@ -50,8 +52,13 @@ type
FHasRoomEvent: PRTLEvent; FHasRoomEvent: PRTLEvent;
FHasItemEvent: PRTLEvent; FHasItemEvent: PRTLEvent;
FShutDown: boolean; FShutDown: boolean;
function TryPushItem(const AItem: T): boolean; function TryPushItem(const AItem: T): boolean; inline;
function TryPopItem(out AItem: T): boolean; function TryPopItem(out AItem: T): boolean; inline;
protected
function TryPushItemUnprotected(const AItem: T): boolean;
function TryPopItemUnprotected(out AItem: T): boolean;
procedure Lock;
procedure Unlock;
public public
constructor create(AQueueDepth: Integer = 10; PushTimeout: cardinal = INFINITE; PopTimeout: cardinal = INFINITE); constructor create(AQueueDepth: Integer = 10; PushTimeout: cardinal = INFINITE; PopTimeout: cardinal = INFINITE);
destructor Destroy; override; destructor Destroy; override;
@ -149,16 +156,7 @@ function TLazThreadedQueue.TryPushItem(const AItem: T): boolean;
begin begin
FMonitor.Enter; FMonitor.Enter;
try try
result := FTotalItemsPushed-FTotalItemsPopped<FQueueSize; result := TryPushItemUnprotected(AItem);
if result then
begin
FList[FTotalItemsPushed mod FQueueSize]:=AItem;
inc(FTotalItemsPushed);
RTLeventSetEvent(FHasItemEvent);
end;
RTLeventResetEvent(FHasRoomEvent);
if FTotalItemsPushed-FTotalItemsPopped<FQueueSize then
RTLeventSetEvent(FHasRoomEvent);
finally finally
FMonitor.Leave; FMonitor.Leave;
end; end;
@ -168,21 +166,50 @@ function TLazThreadedQueue.TryPopItem(out AItem: T): boolean;
begin begin
FMonitor.Enter; FMonitor.Enter;
try try
result := FTotalItemsPushed>FTotalItemsPopped; result := TryPopItemUnprotected(AItem);
if result then
begin
AItem := FList[FTotalItemsPopped mod FQueueSize];
inc(FTotalItemsPopped);
RTLeventSetEvent(FHasRoomEvent);
end;
RTLeventResetEvent(FHasItemEvent);
if FTotalItemsPushed > FTotalItemsPopped then
RTLeventSetEvent(FHasItemEvent);
finally finally
FMonitor.Leave; FMonitor.Leave;
end; end;
end; end;
function TLazThreadedQueue.TryPushItemUnprotected(const AItem: T): boolean;
begin
result := FTotalItemsPushed-FTotalItemsPopped<FQueueSize;
if result then
begin
FList[FTotalItemsPushed mod FQueueSize]:=AItem;
inc(FTotalItemsPushed);
RTLeventSetEvent(FHasItemEvent);
end;
RTLeventResetEvent(FHasRoomEvent);
if FTotalItemsPushed-FTotalItemsPopped<FQueueSize then
RTLeventSetEvent(FHasRoomEvent);
end;
function TLazThreadedQueue.TryPopItemUnprotected(out AItem: T): boolean;
begin
result := FTotalItemsPushed>FTotalItemsPopped;
if result then
begin
AItem := FList[FTotalItemsPopped mod FQueueSize];
inc(FTotalItemsPopped);
RTLeventSetEvent(FHasRoomEvent);
end;
RTLeventResetEvent(FHasItemEvent);
if FTotalItemsPushed > FTotalItemsPopped then
RTLeventSetEvent(FHasItemEvent);
end;
procedure TLazThreadedQueue.Lock;
begin
FMonitor.Enter;
end;
procedure TLazThreadedQueue.Unlock;
begin
FMonitor.Leave;
end;
constructor TLazThreadedQueue.create(AQueueDepth: Integer; PushTimeout: cardinal; PopTimeout: cardinal); constructor TLazThreadedQueue.create(AQueueDepth: Integer; PushTimeout: cardinal; PopTimeout: cardinal);
begin begin
FMonitor:=TLazMonitor.create; FMonitor:=TLazMonitor.create;