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?
Was Sie haben, sollte in Ordnung sein, solange Sie sich an diese Richtlinien halten:
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.
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. 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.
boost::interprocess
bietet plattformübergreifende atomare Funktionen in boost/interprocess/detail/atomic.hpp
Tags und Links c++ concurrency circular-buffer