| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 |
- unit BaseQueue;
- interface
- uses
- SyncObjs;
- {$IFDEF DEBUG}
- {$DEFINE DEBUG_ON}
- {$ENDIF}
- type
- PQueueData = ^TQueueData;
- TQueueData = record
- Data: Pointer;
- Next: PQueueData;
- end;
- TBaseQueue = class(TObject)
- private
- FName: String;
- FLocker: TCriticalSection;
- FCount: Integer;
- FHead: PQueueData;
- FTail: PQueueData;
- {$IFDEF DEBUG_ON}
- FPopCounter:Integer;
- FPushCounter:Integer;
- {$ENDIF}
- /// <summary>
- /// 清空所有数据
- /// </summary>
- procedure clear;
- function innerPop: PQueueData;
- procedure innerAddToTail(AData: PQueueData);
- procedure innerAddToHead(AData: PQueueData);
- public
- constructor Create;
- destructor Destroy; override;
- function IsEmpty: Boolean;
- function size:Integer;
- function Pop: Pointer;overload;
- function Pop(var outPointer:Pointer):Boolean;overload;
- /// <summary>
- /// add to tail
- /// </summary>
- procedure Push(AData: Pointer);
- /// <summary>
- /// add to head
- /// </summary>
- procedure AddToHead(AData: Pointer);
- /// <summary>
- /// invoke Only Data Pointer is TObject
- /// </summary>
- procedure FreeDataObject;
- /// <summary>
- /// dispose all data
- /// </summary>
- procedure DisposeAllData;
- property Name: String read FName write FName;
- end;
- type
- /// <summary>
- /// without lock
- /// </summary>
- TSimpleQueue = class(TObject)
- private
- FName: String;
- FCount: Integer;
- FHead: PQueueData;
- FTail: PQueueData;
- {$IFDEF DEBUG_ON}
- FPopCounter:Integer;
- FPushCounter:Integer;
- {$ENDIF}
- /// <summary>
- /// 清空所有数据
- /// </summary>
- procedure clear;
- function innerPop: PQueueData;
- procedure innerAddToTail(AData: PQueueData);
- procedure innerAddToHead(AData: PQueueData);
- public
- constructor Create;
- destructor Destroy; override;
- function IsEmpty: Boolean;
- function size:Integer;
- function Pop: Pointer;overload;
- function Pop(var outPointer:Pointer):Boolean;overload;
- /// <summary>
- /// add to tail
- /// </summary>
- procedure Push(AData: Pointer);
- /// <summary>
- /// add to head
- /// </summary>
- procedure AddToHead(AData: Pointer);
- /// <summary>
- /// invoke Only Data Pointer is TObject
- /// </summary>
- procedure FreeDataObject;
- /// <summary>
- /// dispose all data
- /// </summary>
- procedure DisposeAllData;
- property Name: String read FName write FName;
- end;
- implementation
- type
- /// <summary>
- /// reference TJobPool in qdac3
- /// </summary>
- TQueueDataPool = class
- protected
- FFirst: PQueueData;
- FCount: Integer;
- FSize: Integer;
- FLocker: TCriticalSection;
- {$IFDEF DEBUG_ON}
- FPopCounter:Integer;
- FPushCounter:Integer;
- {$ENDIF}
- public
- constructor Create(AMaxSize: Integer = 2048); overload;
- destructor Destroy; override;
- procedure Push(pvQueueData: PQueueData);
- function Pop: PQueueData;
- property Count: Integer read FCount;
- property Size: Integer read FSize write FSize;
- end;
- var
- // data pool of PQueueData
- queueDataPool :TQueueDataPool;
- function IsDebugMode: Boolean;
- begin
- {$IFDEF MSWINDOWS}
- {$warn symbol_platform off}
- Result := Boolean(DebugHook);
- {$warn symbol_platform on}
- {$ELSE}
- Result := false;
- {$ENDIF}
- end;
- constructor TBaseQueue.Create;
- begin
- inherited Create;
- FLocker := TCriticalSection.Create();
- FHead := nil;
- FTail := nil;
- FCount := 0;
- FName := 'BaseQueue';
- end;
- destructor TBaseQueue.Destroy;
- begin
- {$IFDEF DEBUG_ON}
- if IsDebugMode then
- Assert(FPopCounter = FPushCounter, ('[' + FName + ']PopCounter <> PushCounter'));
- {$ENDIF}
- Clear;
- FLocker.Free;
- inherited Destroy;
- end;
- procedure TBaseQueue.DisposeAllData;
- var
- lvData:Pointer;
- begin
- while True do
- begin
- lvData := nil;
- if Pop(lvData) then
- begin
- if lvData = nil then
- begin
- lvData := nil;
- end else
- begin
- Dispose(lvData);
- end;
- end else
- begin
- Break;
- end;
- end;
- end;
- { TBaseQueue }
- procedure TBaseQueue.AddToHead(AData: Pointer);
- var
- lvTemp:PQueueData;
- begin
- lvTemp := queueDataPool.Pop;
- lvTemp.Data := AData;
- innerAddToHead(lvTemp);
- end;
- procedure TBaseQueue.clear;
- var
- ANext: PQueueData;
- begin
- FLocker.Enter;
- try
- if FHead = nil then Exit;
- while FHead.Next <> nil do
- begin
- ANext := FHead.Next;
-
- queueDataPool.Push(FHead);
- FHead := ANext;
- end;
- FCount := 0;
- finally
- FLocker.Leave;
- end;
- end;
- procedure TBaseQueue.freeDataObject;
- var
- lvData:Pointer;
- begin
- while True do
- begin
- lvData := nil;
- if Pop(lvData) then
- begin
- if lvData = nil then
- begin
- lvData := nil;
- end else
- begin
- TObject(lvData).Free;
- end;
- end else
- begin
- Break;
- end;
- end;
- end;
- function TBaseQueue.IsEmpty: Boolean;
- begin
- Result := (FHead.next = nil);
- end;
- function TBaseQueue.Pop: Pointer;
- var
- lvTemp:PQueueData;
- begin
- Result := nil;
- lvTemp := innerPop;
- if lvTemp <> nil then
- begin
- Result := lvTemp.Data;
- queueDataPool.Push(lvTemp);
- end;
- end;
- function TBaseQueue.Pop(var outPointer: Pointer): Boolean;
- var
- lvTemp:PQueueData;
- begin
- Result := false;
- lvTemp := innerPop;
- if lvTemp <> nil then
- begin
- outPointer := lvTemp.Data;
- queueDataPool.Push(lvTemp);
- Result := true;
- end;
- end;
- procedure TBaseQueue.Push(AData: Pointer);
- var
- lvTemp:PQueueData;
- begin
- lvTemp := queueDataPool.Pop;
- lvTemp.Data := AData;
- innerAddToTail(lvTemp);
- end;
- function TBaseQueue.size: Integer;
- begin
- Result := FCount;
- end;
- procedure TBaseQueue.innerAddToHead(AData: PQueueData);
- begin
- FLocker.Enter;
- try
- AData.Next := FHead;
- FHead := AData;
- if FTail = nil then FTail := FHead;
- Inc(FCount);
- {$IFDEF DEBUG_ON}
- Inc(FPushCounter);
- {$ENDIF}
- finally
- FLocker.Leave;
- end;
- end;
- function TBaseQueue.innerPop: PQueueData;
- begin
- FLocker.Enter;
- try
- Result := FHead;
- if Result <> nil then
- begin
- FHead := Result.Next;
-
- if FHead = nil then FTail := nil;
- Dec(FCount);
- {$IFDEF DEBUG_ON}
- Inc(FPopCounter);
- {$ENDIF}
- end;
- finally
- FLocker.Leave;
- end;
- end;
- procedure TBaseQueue.innerAddToTail(AData: PQueueData);
- begin
- AData.Next := nil;
- FLocker.Enter;
- try
- if FTail = nil then
- FHead := AData
- else
- begin
- FTail.Next := AData;
- end;
- FTail := AData;
- Inc(FCount);
- {$IFDEF DEBUG_ON}
- Inc(FPushCounter);
- {$ENDIF}
- finally
- FLocker.Leave;
- end;
- end;
- { TQueueDataPool }
- constructor TQueueDataPool.Create(AMaxSize: Integer = 2048);
- begin
- inherited Create;
- FSize := AMaxSize;
- FLocker := TCriticalSection.Create;
- end;
- destructor TQueueDataPool.Destroy;
- var
- lvData: PQueueData;
- begin
- {$IFDEF DEBUG_ON}
- if IsDebugMode then
- Assert(FPopCounter = FPushCounter, ('PopCounter <> PushCounter'));
- {$ENDIF}
- FLocker.Enter;
- while FFirst <> nil do
- begin
- lvData := FFirst.Next;
- Dispose(FFirst);
- FFirst := lvData;
- end;
- FLocker.Free;
- inherited;
- end;
- function TQueueDataPool.Pop: PQueueData;
- begin
- FLocker.Enter;
- Result := FFirst;
- if Result <> nil then
- begin
- FFirst := Result.Next;
- Dec(FCount);
- end;
- {$IFDEF DEBUG_ON}
- Inc(FPopCounter);
- {$ENDIF}
- FLocker.Leave;
- if Result = nil then
- GetMem(Result, SizeOf(TQueueData));
- Result.Data := nil;
- Result.Next := nil;
- end;
- procedure TQueueDataPool.Push(pvQueueData: PQueueData);
- var
- ADoFree: Boolean;
- begin
- Assert(pvQueueData <> nil);
- FLocker.Enter;
- ADoFree := (FCount = FSize);
- if not ADoFree then
- begin
- pvQueueData.Next := FFirst;
- FFirst := pvQueueData;
- Inc(FCount);
- end;
- {$IFDEF DEBUG_ON}
- Inc(FPushCounter);
- {$ENDIF}
- FLocker.Leave;
-
- if ADoFree then
- begin
- FreeMem(pvQueueData);
- end;
- end;
- constructor TSimpleQueue.Create;
- begin
- inherited Create;
- FHead := nil;
- FTail := nil;
- FCount := 0;
- FName := 'simpleQueue';
- end;
- destructor TSimpleQueue.Destroy;
- begin
- {$IFDEF DEBUG_ON}
- if IsDebugMode then
- Assert(FPopCounter = FPushCounter, ('[' + FName + ']PopCounter <> PushCounter'));
- {$ENDIF}
- Clear;
- inherited Destroy;
- end;
- procedure TSimpleQueue.DisposeAllData;
- var
- lvData:Pointer;
- begin
- while True do
- begin
- lvData := nil;
- if Pop(lvData) then
- begin
- if lvData = nil then
- begin
- lvData := nil;
- end else
- begin
- Dispose(lvData);
- end;
- end else
- begin
- Break;
- end;
- end;
- end;
- { TSimpleQueue }
- procedure TSimpleQueue.AddToHead(AData: Pointer);
- var
- lvTemp:PQueueData;
- begin
- lvTemp := queueDataPool.Pop;
- lvTemp.Data := AData;
- innerAddToHead(lvTemp);
- end;
- procedure TSimpleQueue.clear;
- var
- ANext: PQueueData;
- begin
- if FHead = nil then Exit;
- while FHead.Next <> nil do
- begin
- ANext := FHead.Next;
- queueDataPool.Push(FHead);
- FHead := ANext;
- end;
- FCount := 0;
- end;
- procedure TSimpleQueue.freeDataObject;
- var
- lvData:Pointer;
- begin
- while True do
- begin
- lvData := nil;
- if Pop(lvData) then
- begin
- if lvData = nil then
- begin
- lvData := nil;
- end else
- begin
- TObject(lvData).Free;
- end;
- end else
- begin
- Break;
- end;
- end;
- end;
- function TSimpleQueue.IsEmpty: Boolean;
- begin
- Result := (FHead.next = nil);
- end;
- function TSimpleQueue.Pop: Pointer;
- var
- lvTemp:PQueueData;
- begin
- Result := nil;
- lvTemp := innerPop;
- if lvTemp <> nil then
- begin
- Result := lvTemp.Data;
- queueDataPool.Push(lvTemp);
- end;
- end;
- function TSimpleQueue.Pop(var outPointer: Pointer): Boolean;
- var
- lvTemp:PQueueData;
- begin
- Result := false;
- lvTemp := innerPop;
- if lvTemp <> nil then
- begin
- outPointer := lvTemp.Data;
- queueDataPool.Push(lvTemp);
- Result := true;
- end;
- end;
- procedure TSimpleQueue.Push(AData: Pointer);
- var
- lvTemp:PQueueData;
- begin
- lvTemp := queueDataPool.Pop;
- lvTemp.Data := AData;
- innerAddToTail(lvTemp);
- end;
- function TSimpleQueue.size: Integer;
- begin
- Result := FCount;
- end;
- procedure TSimpleQueue.innerAddToHead(AData: PQueueData);
- begin
- AData.Next := FHead;
- FHead := AData;
- if FTail = nil then FTail := FHead;
- Inc(FCount);
- {$IFDEF DEBUG_ON}
- Inc(FPushCounter);
- {$ENDIF}
- end;
- function TSimpleQueue.innerPop: PQueueData;
- begin
- Result := FHead;
- if Result <> nil then
- begin
- FHead := Result.Next;
- if FHead = nil then FTail := nil;
- Dec(FCount);
- {$IFDEF DEBUG_ON}
- Inc(FPopCounter);
- {$ENDIF}
- end;
- end;
- procedure TSimpleQueue.innerAddToTail(AData: PQueueData);
- begin
- AData.Next := nil;
- if FTail = nil then
- FHead := AData
- else
- begin
- FTail.Next := AData;
- end;
- FTail := AData;
- Inc(FCount);
- {$IFDEF DEBUG_ON}
- Inc(FPushCounter);
- {$ENDIF}
- end;
- initialization
- queueDataPool := TQueueDataPool.Create(10240);
- finalization
- queueDataPool.Free;
- end.
|