Ich habe einen Container (C ++), auf dem ich auf zwei Arten arbeiten muss, aus verschiedenen Threads: 1) Hinzufügen und Entfernen von Elementen und 2) Iterieren durch seine Mitglieder. Entfernen Sie das Element eindeutig, während die Iteration stattfindet = Disaster. Der Code sieht etwa so aus:
%Vor% Auch hier werden B::SomeFunction()
und C::IterateOverStuff()
asynchron aufgerufen. Was ist eine Datenstruktur, die ich verwenden kann, um sicherzustellen, dass my_stuff
während der Iteration vor Operationen zum Hinzufügen oder Entfernen geschützt ist?
klingt wie eine Lese- / Schreibsperre . Grundsätzlich besteht die Idee darin, dass Sie einen oder mehrere Leser ODER einen einzigen Autor haben. Nie können Sie gleichzeitig eine Lese- und Schreibsperre haben.
BEARBEITEN: Ein Anwendungsbeispiel, das Ihrer Meinung nach zu Ihrem Design passt, ist eine kleine Änderung. Fügen Sie der Klasse, die die Liste besitzt, eine "iterate" -Funktion hinzu und machen Sie sie zu einem Template, damit Sie eine Funktion / einen Funktor übergeben können, um festzulegen, was für jeden Knoten zu tun ist. Etwas wie das (schnell und schmutzig Pseudocode, aber Sie bekommen den Punkt ...):
%Vor%Eine andere Option wäre, die Lese- / Schreibsperre für die Öffentlichkeit zugänglich zu machen und den Anrufer für die korrekte Verwendung der Sperre verantwortlich zu machen. Aber das ist fehleranfälliger.
IMHO ist es ein Fehler, einen privaten Mutex in einer Datenstrukturklasse zu haben und dann die Klassenmethoden zu schreiben, so dass die ganze Sache threadsicher ist, egal was der Code, der die Methoden aufruft, tut. Die Komplexität, die erforderlich ist, um dies vollständig und perfekt zu tun, ist weit übertrieben.
Der einfachste Weg besteht darin, einen öffentlichen (oder globalen) Mutex zu haben, den der aufrufende Code für das Sperren verantwortlich macht, wenn er auf die Daten zugreifen muss.
Hier ist mein Blog-Artikel zu diesem Thema .
Wenn Sie die Liste zurückgeben, geben Sie sie in einer Klasse zurück, die den Mutex in seinem Konstruktor / Destruktor sperrt / entsperrt. Etwas in der Art von
%Vor%Der schwierige Teil besteht darin, einen Kopierkonstruktor zu schreiben, damit der Mutex nicht rekursiv sein muss. Oder benutze einfach auto_ptr.
Oh, und Reader / Writer-Lock ist in der Tat eine bessere Lösung als Mutex hier.
Tags und Links c++ thread-safety iteration iterator containers