2009-07-05 3 views
11

Ich habe mehrere Implementierungen für Single-Producer-Single-Consumer gefunden, aber keine für mehrere Producer-Single-Consumer.Gibt es für Delphi eine blockierungsfreie Warteschlange "mehrere Producer - Single Consumer"?

Gibt es eine sperrfreie Warteschlange für "mehrere Produzenten - Einzelverbraucher" für Delphi?

+1

Eine sehr interessante Antwort in Bezug auf Performance-Tuning mit Lock-Free-Algorithmen und Alternativen: http://stackoverflow.com/questions/853316/is-critical-section-always-faster/853510#853510. – mghie

Antwort

5

Lock-freie Warteschlange von der OmniThreadLibrary unterstützt mehrere Hersteller. Sie können es separat von der Threading-Bibliothek verwenden (d. H. Sie können die OtlContainers-Einheit in jedem anderen Framework verwenden).

Wie der Daniele unten zeigt, gibt es zwei Warteschlangen in der OmniThreadLibrary. Der eine in den OtlContainern unterstützt mehrere Produzenten und mehrere Konsumenten, während die "smartere" Version in OtlComm (die nur ein Wrapper für die einfachere Version ist) nur ein einzelner Erzeuger/einzelner Verbraucher ist.

Dokumentation ist nach wie vor ein großes Problem des OmniThreadLibrary Projektes :(. Können einige Informationen über die Warteschlange here finden.

+0

Wirklich? Ich benutzte deine Liste, aber im Quellcode ist das ein "trauriger" Kommentar für mich ... "{: Lock-free, einzelner Schreiber, einzelner Leser Ringpuffer. } IOmniQueue = interface [ '{AE6454A2-CDB4-43EE-9F1B-5A7307593EE9}']“ Sie sagen, dass OmniQueue MULTI Produzenten, Einzel Verbraucher aktiviert? –

+0

Sorry, mein Fehler. "High-Level" Warteschlange in OtlComm ist Single Producer/Single Consumer. "Low-Level" -Warteschlange in OtlContainers ist mehrere Producer/Multiple Consumers. Sie müssen also die einfachere Variante des Queue-Objekts verwenden, wenn Sie mehrere Producer verwenden wollen. Ich habe den obigen Text korrigiert beziehen Sie sich auf den korrekten Gerätenamen. – gabr

3

Vielleicht könnte das hilfreich sein: Interlocked SList functions.

+0

+1. Beachten Sie, dass eine Alternative dazu implementiert werden muss, wenn die Anwendungen auf Windows XP-Systemen vor der Installation ausgeführt werden müssen. Beachten Sie auch, dass es keine einfache Möglichkeit gibt, den Verbraucher in einer leeren Warteschlange blockieren zu lassen. – mghie

+0

Die SList-Funktionen generieren einen Stapel, keine Warteschlange. –

+2

@Rob Kennedy: Nicht ganz richtig, wenn der Verbraucher InterlockedFlushSList() anstelle von InterlockedPopEntrySList() verwendet, ist es frei, die Listenelemente in beide Richtungen zu verarbeiten. – mghie

2

http://svn.berlios.de/svnroot/repos/dzchart/utilities/dzLib/trunk/lockfree/

@Daniele Teti:

Der Leser für alle Autoren warten müssen, die noch Zugang zum alten Warteschlange müssen die Enqueue Methode zu verlassen. Da der Leser bei der Dequeue-Methode als erstes eine neue Warteschlange für neue Writer bereitstellt, die Enqueue eingeben, sollte es nicht lange dauern, bis alle Writer, die einen Verweis auf die alte Queue haben, Enqueue beenden. Aber Sie haben recht: Es ist nur für die Schreiber frei, aber es kann sein, dass der Leser-Thread noch auf einige Schreiber wartet, um Enqueue zu beenden.

+1

Ich tring diese Liste, aber ... Code-Kommentare sind seltsam für eine "LockFree" -Liste: "// Leider ist es möglich, dass andere Threads immer noch einen // Verweis auf die alte Warteschlange halten. // Um ​​100% sicher zu sein, müssen wir warten, bis der ActiveWriters-Zähler // auf 0 fällt // Wenn derzeit Writer vorhanden sind, warten wir auf das Ereignis //, das vom ersten Writer gesetzt wird, der dekrementiert // ActiveWriters auf 0. Wenn nicht, müssen Sie nicht warten. " Dies scheint eine Art" Warten "-Synchronisation zu sein ... Ich liege falsch? (Ich bin diese Kommentare innerhalb der Funktion TMultiWriteSingleReadLockFreeQueue.Dequeue gefunden) –

2

Für ein Mehr Hersteller/Single-Consumer-Queue/FIFO, Sie leicht ein LockFree machen mit SLIST oder einem trivialen Lock Free LIFO Stack. Was Sie tun, ist ein zweiter "privater" Stack für den Konsumenten (der auch als SLIST zur Vereinfachung oder für jedes andere von Ihnen gewählte Stack-Modell verwendet werden kann) Privater Stapel: Immer wenn das private LIFO ausgeatmet wird, führt man einen Flush aus, anstatt das gemeinsame gleichzeitige SLIST abzubrechen (die gesamte SLIST-Kette zu greifen) und dann die Flushed-Liste zu durchlaufen, um Elemente auf den privaten Stapel zu schieben

Das funktioniert für Single-Producer/Single-Consumer und für Multiple-Producer/Single-Consumer.

Es funktioniert jedoch nicht für Multiple-Producer/Multiple-Consumer-Fälle.

Verwandte Themen