![]() |
TThreadedQueue vs ThreadedRingBuffer
TThreadedQueue aus System.Generics.Collections
Führt bei jedem PushItem oder PopItem sowas hier durch
Delphi-Quellcode:
Wenn ich Queue als Ringpuffer umsetzen würde , müsste ich dann immer noch beides LOCKEN also READ und WRITE oder kann ich READ während des WRITE ungelockt lassen ?
TMonitor.Enter(FQueueLock); // ALLES WIRD GELOCKT
try Result := wrSignaled; while (Result = wrSignaled) and (FQueueSize = Length(FQueue)) and not FShutDown do if not TMonitor.Wait(FQueueNotFull, FQueueLock, FPushTimeout) then Result := wrTimeout; if FShutDown or (Result <> wrSignaled) then Exit; FQueue[(FQueueOffset + FQueueSize) mod Length(FQueue)] := AItem; Inc(FQueueSize); Inc(FTotalItemsPushed); finally AQueueSize := FQueueSize; TMonitor.Exit(FQueueLock); end; TMonitor.Pulse(FQueueNotEmpty); Edit: Ich sehe gerade DASS es sich bei TThreadedQueue um einen Ringbuffer handelt. Warum wird jedesmal alles gelockt? |
AW: TThreadedQueue vs ThreadedRingBuffer
Zitat:
Ich denke das Queue hat eine variable Größe/Kapazität, worauf auch diese Zeile hindeutet:
Delphi-Quellcode:
Inc(FQueueSize);
Bei einem Ringbuffer sollte es meiner Meinung nach eine feste Kapazität geben, die sich nicht vergrößert/verkleinert, sondern überschrieben werden, wenn es über die Kapazität hinausgeht. |
AW: TThreadedQueue vs ThreadedRingBuffer
Es ist ein Ringpuffer
FqueueSize minus fqueueOffset Ist die Länge der Schlange im Ringpuffer. FQueueSize hat vielleicht nicht ganz den richtigen Bezeichner! Length(FQueue) ist die größe des Ringpuffers. FQueue ist ein Array = Der Puffer. Der Schreib-Index des Ringpuffers wird wie folgt ermittelt
Code:
FQueueSize modulo 10
(FQueueOffset + FQueueSize) mod Length(FQueue)
ergibt indizes 0..9 in einem RING FQueueSize = 1401 würde einen index 1 ergeben da 1401 modulo 10 gleich 1 ist! man kann FQueueSize einfach immer hochzählen solange man den index über modulo ermittelt. |
AW: TThreadedQueue vs ThreadedRingBuffer
Queue = FIFO (first in, first out)
Stack = LIFO (last in, first out) Also ja Queue gleich entsprechend RingBuffer ... praktisch das gleiche Verhalten, also es unterscheidet sich nur die interne Speicherverwaltung. Und da die TThreaded-Komponenten ja selbst das Threadsichere handhaben, kann man da meistens direkt auf Add/Remove/Push/Pop/... zugreifen, weil sie intern sich selbst absichern (wenn diese Methoden direkt oben public erreichbar sind) Als Ringbuffer oder verkettete Liste hat es halt den Vorteil, dass beim Reinschieben oder Rausholen nicht der gesamte Listeninhalt verschoben werden muß. (beim Stack geht ist Beides immer am Listenende und somit verschieben sich die vorherrigen Einträge nicht) |
AW: TThreadedQueue vs ThreadedRingBuffer
Zitat:
Dafür kann es aber auch einen Überlauf geben. |
AW: TThreadedQueue vs ThreadedRingBuffer
Zitat:
Intern speichert es einen ReadPointer "FQueueOffset mod length(fQueue)" in form eines index auf ein Array und einen WritePointer "(FQueueOffset + fQueSize) mod length(fQueue)" ebenfalls als index auf das Array fQueue. Zitat:
Vermutlich müsste es dafür ein Ringspeicher auf Basis einer Verkettetenliste sein? |
AW: TThreadedQueue vs ThreadedRingBuffer
Zitat:
Und das meine ich ausnahmsweise mal nicht despektierlich, das ist nämlich wirklich kein Zuckerschlecken sonst hätt ich sowas auch in Spring4D, aber davon lass ich lieber die Finger 8-) Wenn du sowas benötigst, solltest du dich eher bei externen Bibliotheken umschauen, z.B. der OTL. Übrigens, lockfrei ist auch nicht wirklich der heilige Gral, da gibt es noch ![]() |
AW: TThreadedQueue vs ThreadedRingBuffer
Ich habe drüber nachgedacht...
um es semi-Lockfrei zu halten müsste ich dafür sorgen das im Ringpuffer immer mindestesens zwei Einträge sind...also auch im leeren Ringpuffer müssten 2 dummy einträge sein... Und dann könnte ich lesen und schreiben unabhängig von einander Locken... nur so zur sicherheit...aber das wäre effektiv so dass kein thread je auf das unlock warten müsste (Waitfree)...es sei denn es läuft etwas schief. |
AW: TThreadedQueue vs ThreadedRingBuffer
Zitat:
Ist es das hier? ![]() Verstehst du das? Edit: OK es gibt hier eine Erklärung ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz