Mehrere Threads schreiben nach std :: cout oder std :: cerr

8

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?

    
Wolfgang 22.02.2013, 21:54
quelle

4 Antworten

21

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:

%Vor%

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.

    
stefan 22.02.2013 22:52
quelle
9

Sie können einen Ansatz verwenden, der einem Zeichenfolgengenerator ähnelt. Erstellen Sie eine Nicht-Template-Klasse, die:

  • bietet die Vorlage " operator<< " zum Einfügen in dieses Objekt
  • baut intern in ein std::ostringstream auf
  • dumps den Inhalt auf Zerstörung

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* ),

    
quelle
0

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.

    
Some programmer dude 22.02.2013 22:00
quelle
0

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%     
Andras Fekete 21.12.2015 20:07
quelle