Ringpuffer ohne Prioritätsumkehrung

8

Ich habe einen Prozess mit hoher Priorität, der Daten an einen Prozess mit niedriger Priorität weiterleiten muss. Ich habe einen grundlegenden Ringpuffer geschrieben, um die Weitergabe von Daten zu behandeln:

%Vor%

Hier ist das Problem. Angenommen, der Prozess mit niedriger Priorität hat ein Orakel, das genau angibt, wie viele Daten gelesen werden müssen, sodass count() niemals aufgerufen werden muss. Dann (außer ich verpasse etwas) gibt es keine Nebenläufigkeitsprobleme. Sobald jedoch der Thread mit niedriger Priorität count() aufrufen muss (der Thread mit hoher Priorität möchte ihn möglicherweise auch aufrufen, um zu prüfen, ob der Puffer zu voll ist), besteht die Möglichkeit, dass die Berechnung in count () oder dem update to end ist nicht atomar und führt zu einem Bug.

Ich könnte einen Mutex um die Zugriffe legen, um zu beginnen und zu enden, aber das würde eine Prioritätsumkehrung verursachen, wenn der Thread mit hoher Priorität auf die Sperre warten muss, die von dem Thread mit niedriger Priorität erhalten wird.

Ich könnte etwas mit atomaren Operationen erledigen, aber mir ist keine nette, plattformübergreifende Bibliothek bekannt, die diese bereitstellt.

Gibt es ein Standard-Ringpuffer-Design, das diese Probleme vermeidet?

    
user168715 21.04.2011, 15:51
quelle

3 Antworten

4

Was Sie haben, sollte in Ordnung sein, solange Sie sich an diese Richtlinien halten:

  • Nur ein Thread kann schreiben.
  • Nur ein Thread kann Lesevorgänge ausführen.
  • Updates und Zugriffe auf start und end sind atomar. Dies kann automatisch sein, zum Beispiel sagt Microsoft:
  

Einfaches Lesen und Schreiben in   richtig ausgerichtete 32-Bit-Variablen sind   atomare Operationen. Mit anderen Worten, du   wird nicht mit nur einer Portion enden   der Variablen aktualisiert; alle Bits sind   auf atomare Weise aktualisiert.

  • Sie berücksichtigen, dass count möglicherweise veraltet ist, selbst wenn Sie den Wert erhalten. Im Lese-Thread gibt count die minimale Anzahl zurück, auf die Sie sich verlassen können. Für den Schreib-Thread gibt count die maximale Anzahl zurück und die wahre Anzahl könnte niedriger sein.
Mark Ransom 21.04.2011, 16:11
quelle
2

Boost bietet einen kreisförmigen Puffer, aber es ist nicht threadsicher. Leider kenne ich keine Implementierung.

Der kommende C ++ - Standard fügt der Standardbibliothek atomare Operationen hinzu, so dass sie in Zukunft verfügbar sein werden, aber von den meisten Implementierungen noch nicht unterstützt werden.

Ich sehe keine plattformübergreifende Lösung, um count sane beizubehalten, während beide Threads darauf schreiben, es sei denn, Sie implementieren das Sperren.

Normalerweise würden Sie wahrscheinlich ein Messaging-System verwenden und den Thread mit niedriger Priorität zwingen, zu fordern, dass der Thread mit hoher Priorität Aktualisierungen vornimmt, oder Ähnliches. Wenn der Thread mit niedriger Priorität beispielsweise 15 Byte verbraucht, sollte er den Thread mit hoher Priorität auffordern, die Anzahl um 15 zu verringern.

Im Wesentlichen würden Sie den Schreibzugriff auf den Thread mit hoher Priorität beschränken und den Thread mit niedriger Priorität nur lesen. Auf diese Weise können Sie alle Sperren vermeiden, und der Thread mit hoher Priorität muss sich nicht darum sorgen, dass ein Schreibvorgang vom untergeordneten Thread abgeschlossen wird, wodurch der Thread mit hoher Priorität eine wirklich hohe Priorität erhält.

    
Collin Dauphinee 21.04.2011 16:16
quelle
1

boost::interprocess bietet plattformübergreifende atomare Funktionen in boost/interprocess/detail/atomic.hpp

    
Khaled Nassar 21.04.2011 16:25
quelle