Ich habe OpenMP-Threads, die über cout und cerr auf die Konsole schreiben. Dies ist natürlich nicht sicher, da die Ausgabe verschachtelt werden kann. Ich könnte etwas wie
machen %Vor%Es wäre schöner, wenn wir cerr durch eine thread-sichere Version ersetzen könnten, ähnlich wie im Valgrind-DRD-Handbuch beschrieben ( Ссылка ), was das Ableiten einer Klasse von std :: ostreambuf beinhaltet. Idealerweise würde ich am Ende cerr durch meinen eigenen cerr ersetzen, z. einfach:
%Vor%Eine solche Klasse könnte auf der Konsole drucken, sobald sie auf ein "endl" stößt. Es macht mir nichts aus, wenn Zeilen aus verschiedenen Threads verschachtelt sind, aber jede Zeile sollte nur aus einem Thread kommen.
Ich verstehe nicht wirklich, wie all dieses Streaming in C ++ funktioniert, es ist zu kompliziert. Hat jemand solch eine Klasse oder kann mir zeigen, wie man eine solche Klasse für diesen Zweck erstellt?
Wie andere darauf hingewiesen haben, ist std::cout
in C ++ 11 threadsicher.
Allerdings, wenn Sie es wie
verwenden %Vor% Bei verschiedenen Threads kann die Ausgabe immer noch interleaved sein, da jedes <<
ein neuer Funktionsaufruf ist, dem ein Funktionsaufruf auf einem anderen Thread vorausgehen kann.
Um Interleaving zu vermeiden ohne a #pragma omp critical
- was würde alles sperren - können Sie Folgendes tun:
Die drei Aufrufe von 123 in den Stream erfolgen nur in einem Thread an ein lokales, nicht gemeinsam genutztes Objekt und sind daher von keinen anderen Threads betroffen. Dann gibt es nur einen Aufruf für den freigegebenen Ausgabestream std::cout
, wobei die Reihenfolge der Elemente 123 bereits festgelegt ist und daher nicht durcheinander gebracht wird.
Sie können einen Ansatz verwenden, der einem Zeichenfolgengenerator ähnelt. Erstellen Sie eine Nicht-Template-Klasse, die:
operator<<
" zum Einfügen in dieses Objekt std::ostringstream
auf
Grobe Annäherung:
%Vor%Verwenden Sie als:
%Vor%Oder in komplexeren Szenarien:
%Vor% Sie müssen mehr Überladungen hinzufügen, wenn Sie Manipulatoren wollen, Sie können write
besser als fprintf
für die atomare Schreibweise im Destruktor verwenden, oder std::cerr
, Sie können dies verallgemeinern dass das Ziel an den Konstruktor übergeben wird ( std::ostream
/ Dateideskriptor / FILE*
),
Sie können dies tun, indem Sie std::basic_streambuf
erben und die korrekten Funktionen überschreiben, um sie sicherer zu machen . Verwenden Sie diese Klasse dann für Ihre Stream-Objekte.
Ich habe nicht genug Reputation, um einen Kommentar zu schreiben, aber ich wollte meinen Zusatz zur AtomicWriter-Klasse veröffentlichen, um std :: endl zu unterstützen und zu erlauben, dass neben std :: cout auch andere Streams verwendet werden. Hier ist es:
%Vor%Tags und Links c++ multithreading openmp valgrind