2010-10-13 7 views
15

In der in VS2010 eingeführten Concurrency-Laufzeit gibt es eine concurrent_queue-Klasse. Es hat eine nicht blockierende Funktion try_pop().
Ähnlich wie in Intel-Thread-Building-Blöcken (TBB) wurde der blocking pop() -Aufruf entfernt, als von Version 2.1 auf 2.2 gewechselt wurde.Warum ist die concurrent_queue nicht blockierend?

Ich frage mich, was das Problem mit einem blockierenden Anruf ist. Warum wurde es von TBB entfernt? Und warum gibt es keine gleichzeitige Warteschlange?

Ich bin in einer Situation, in der ich eine blockierende gleichzeitige Warteschlange benötigen, und ich möchte nicht beschäftigt warten. Abgesehen davon, dass ich selbst eine Queue schreibe, gibt es noch eine andere Möglichkeit in der Laufzeitumgebung?

Antwort

25

Von a comment from Arch Robison, und es ist nicht viel mehr "horse's mouth" als (a):


PPL concurrent_queue kein Blockieren schiessen, daher auch nicht tbb::strict_ppl::concurrent_queue. Der blockierende Pop ist in tbb::concurrent_bounded_queue verfügbar. Das Entwurfsargument für das Weglassen von Blocking Pop ist, dass in vielen Fällen die Synchronisation für die Blockierung außerhalb der Warteschlange bereitgestellt wird. In diesem Fall wird die Implementierung der Blockierung innerhalb der Warteschlange unnötig.

Auf der anderen Seite war die Blockierung Pop der alten tbb::concurrent_queue beliebt bei Benutzern, die keine externe Synchronisation hatten.

Also wir teilen die Funktionalität. Anwendungsfälle, die keine Blockierung oder Begrenzung benötigen, können das neue tbb::concurrent_queue verwenden, und Anwendungsfälle, die es benötigen, können tbb::concurrent_bounded_queue verwenden.


(a) Arch ist der Architekt Threading Building Blocks.

4

Wenn Sie einen blockierenden Pop ohne Wartezeit benötigen, benötigen Sie eine Signalisierungsmethode. Dies impliziert eine Synchronisation zwischen Pusher und Poper und die Warteschlange ist nicht länger ohne (teure) Synchronisationsgrundelemente. Sie erhalten im Grunde eine normale synchronisierte Warteschlange mit einer Zustandsvariablen, die verwendet wird, um POPPERS von Pushs zu benachrichtigen, was nicht in der Eigenschaft der currently_ * -Sammlungen ist.

0

Es gibt keine Situation, aus der Sicht der Warteschlange, dass benötigt, um für eine Einfügung zu blockieren oder zu entfernen. Die Tatsache, dass Sie einen Einsatz blockieren und warten müssen, ist unerheblich.

Sie können die gewünschte Funktionalität erreichen, indem Sie eine Bedingungsvariable oder ein Zähl-Semaphor oder etwas in dieser Richtung verwenden (unabhängig von Ihrer spezifischen API). Ihr Problem besteht nicht in Blockieren/Nicht-Blockieren; Es klingt wie ein klassischer Produzent-Verbraucher.

+2

Mit einer Blockierung 'pop', können Sie * implementieren *„klassischen Erzeuger-Verbraucher“mit TBB in etwa zwei Codezeilen, ohne dass irgendwelche Synchronisierungsgrund selbst zu schreiben. (Der Konsument tut 'while (true) konsumiert (Q.pop());' und der Produzent tut 'while (true) Q.push (produce());'.) Ohne ein blockierendes 'pop', das gleiche Problem erfordert mindestens doppelt so viel Code: nämlich Buchhaltung eine zusätzliche Zustandsvariable pro Warteschlange. Aber wie paxdiablo sagt, 'tbb :: concurrent_bounded_queue' liefert weiterhin die blockierende' pop'-Funktionalität und ist im Grunde ein Ersatz für 'concurrent_queue'. – Quuxplusone

2

Die Frage war, ob es eine andere Option in der Concurrency Runtime gab, die blockierende Warteschlangenfunktionalität bietet, weil concurrent_queue nicht und es gibt eine in VS2010.

Arch Kommentar ist natürlich völlig richtig, Sperrung Warteschlangen und Entsperrung Warteschlangen sind separate Anwendungsfälle und das ist, warum sie in VS2010 und in TBB unterschiedlich sind.

In VS2010 können Sie die Template-Klasse unbounded_buffer in verwenden, die entsprechenden Methoden heißen Enqueue und Dequeue.

-Rick

Verwandte Themen