Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to easily make std::cout thread-safe?

I have a multi-threaded application, which heavily uses std::cout for logging without any locking. In such a case, how can I easily add lock mechanism to make std::cout thread-safe?

I don't want to search for each occurrence of std::cout and add a line of locking code. That is too tedious.

Any better practice?

like image 437
xmllmx Avatar asked Feb 05 '13 22:02

xmllmx


People also ask

Is std :: cout safe?

A side note: std::cout is thread-safe The C++11 standard guarantees, that you must not protect the single characters, written to std::cout. Each character will atomically be written. Of course, it is possible, that more output statements like in the example will interleave. But that is only an optical issue.

How do you ensure thread safety in C++?

An object is thread-safe for reading from multiple threads. For example, given an object A, it is safe to read A from thread 1 and from thread 2 simultaneously. If an object is being written to by one thread, then all reads and writes to that object on the same or other threads must be protected.

Are C++ streams thread-safe?

Streams in C++ are not thread-safe by default. However, using the power of STL and the coding techniques outlined here, you can benefit from the simplicity of streams while maintaining thread-safe code.

Is C++ set thread-safe?

It is safe to read and write to one instance of a type even if another thread is reading or writing to a different instance of the same type.


1 Answers

While I can't be sure this applies to every compiler / version of std libs but in the code-base I'm using std::cout::operator<<() it is already thread-safe.

I'm assuming that what you're really trying to do it stop std::cout from mixing string when concatenating with the operator<< multiple time per string, across multiple threads.

The reason strings get garbled is because there is a "External" race on the operator<< this can lead to things like this happening.

//Thread 1 std::cout << "the quick brown fox " << "jumped over the lazy dog " << std::endl;  //Thread 2 std::cout << "my mother washes" << " seashells by the sea shore" << std::endl;  //Could just as easily print like this or any other crazy order. my mother washes the quick brown fox seashells by the sea shore \n jumped over the lazy dog \n 

If that's the case there is a much simpler answer than making your own thread safe cout or implementing a lock to use with cout.

Simply compose your string before you pass it to cout

For example.

//There are other ways, but stringstream uses << just like cout..  std::stringstream msg; msg << "Error:" << Err_num << ", " << ErrorString( Err_num ) << "\n";  std::cout << msg.str(); 

This way your stings can't be garbled because they are already fully formed, plus its also a better practice to fully form your strings anyway before dispatching them.

like image 198
Nickolas George Avatar answered Sep 22 '22 14:09

Nickolas George