Nutzung von STL-Streams für einfache und thread-sichere Protokollierung in C++

Streams in C++ sind nicht bereits standardmäßig thread-sicher. Doch mithilfe der STL und der hier geschilderten Programmiermethoden ist es möglich, die einfache Handhabung von Streams zu nutzen und gleichzeitig den Code thread-sicher zu gestalten.

Streams bieten eine leistungsfähige Abstraktionsoption zur Handhabung von Daten, da sie unabhängig von der Herkunft oder dem Ziel der Daten ein Aufrufen allgemeiner Lese- und Schreibfunktionen ermöglichen. Mithilfe von Streams kann man denselben Code für das Lesen von Konsolen, Dateien, Sockets usw. verwenden.

C++ kombiniert diese Fähigkeit mit dem Überladen von Operatoren und liefert die Operatoren >> und << für das Lesen aus bzw. Schreiben in Streams, wie in Listing A gezeigt.

Das Schreiben in Streams ist gewöhnlich nicht thread-sicher. Tatsächlich müssen nicht einmal simple Funktionen wie fread und fwrite unbedingt thread-sicher sein. Sauber implementierte STL-Streams (Standard Template Library) ermöglichen jedoch eine Nutzung der einfachen Handhabung von Streams bei gleichzeitig thread-sicherem Code. Darüber hinaus können weiterhin bestehende Programmiermethoden mithilfe des Operators << verwendet werden, während die Thread-sicherheit im Hintergrund gewährleistet wird.

Weshalb STL-Streams nicht standardmäßig thread-sicher sind

Der Standard für C++ legt nicht fest, ob das Schreiben in Streams thread-sicher ist, doch zumeist ist dies nicht der Fall. Dies ist vorwiegend eine Frage der Effizienz. Wenn das Schreiben in Streams thread-sicher wäre, müssten sämtliche öffentlichen (und einige geschützte) Funktionen ebenfalls thread-sicher sein. Gemäß der STL-Dokumentation besitzt die Klasse basic_ostream<>, die Basis-Klasse für alle Ausgabe-Streams, zahlreiche öffentliche Funktionen. Dazu der folgende Code:


Um das Schreiben in std::cout thread-sicher zu machen, wären mindestens 2.000.000 Locks erforderlich, was zu einem enormen Performance-Engpass führen würde.

Dazu kommt, dass bei einer Nutzung von Stream-Puffern auch diese Puffer thread-sicher gemacht werden müssten. Die Erweiterung einer STL-Stream-Klasse würde durch die Thread-sicherheit bedingt ein noch größeres Performance-Problem mit sich bringen. Und schließlich würde selbst bei thread-sicheren STL-Streams ein Code wie in Listing B nicht zwangsläufig die gewünschten Ergebnisse liefern.

Auf den ersten Blick scheint es, dass Listing B die folgende Ausgabe auf der Konsole erzeugen sollte:


message from thread 1
message from thread 2

Stattdessen sieht das Ergebnis wie folgt aus:


message from message from thread 2
thread 1

Dies liegt daran, dass nach dem erfolgreichen Ausführen des ersten Threads mit der Ausgabe von message und from der zweite Thread übernimmt und die gesamte Mitteilung druckt, worauf der erste Thread an der Stelle weitermacht, wo er aufgehört hatte. Dies nur als ganz einfaches Beispiel dafür, welche Probleme sich durch nicht thread-sicheren Code ergeben können.

Protokollieren ist einfacher als Schreiben

Streams ermöglichen eine Positionierung, die dem Gewähren eines Dateizugriffs ähnelt. Man kann bis zu Mitte eines Streams vorrücken (sofern der Stream dies erlaubt) und von dort aus mit dem Schreiben beginnen. Wenn man dagegen Informationen protokolliert, werden diese immer am Ende hinzugefügt. Es ist daher keine Positionierung erforderlich, man befindet sich immer am Ende. Zur Vereinfachung lassen unsere Protokoll-Klassen erst gar keine Positionierung zu.

Themenseiten: Anwendungsentwicklung, Software

Fanden Sie diesen Artikel nützlich?
Content Loading ...
Whitepaper

Artikel empfehlen:

Neueste Kommentare 

Noch keine Kommentare zu Nutzung von STL-Streams für einfache und thread-sichere Protokollierung in C++

Kommentar hinzufügen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *