Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

multiple threads writing to std::cout or std::cerr

I have OpenMP threads that write to the console via cout and cerr. This of course is not safe, since output can be interleaved. I could do something like

#pragma omp critical(cerr)
{
   cerr << "my variable: " << variable << endl;
}

It would be nicer if could replace cerr with a thread-safe version, similar to the approach explained in the valgrind DRD manual (http://valgrind.org/docs/manual/drd-manual.html#drd-manual.effective-use) which involves deriving a class from std::ostreambuf. Ideally in the end I would just replace cerr with my own threaded cerr, e.g. simply:

tcerr << "my variable: " << variable << endl;

Such a class could print to the console as soon as it encounters an "endl". I do not mind if lines from different threads are interleaved, but each line should come only from one thread.

I do not really understand how all this streaming in C++ works, it is too complicated. Has anybody such a class or can show me how to create such a class for that purpose?

like image 839
Wolfgang Avatar asked Feb 22 '13 21:02

Wolfgang


People also ask

Is std :: CERR thread-safe?

Insertion to and extraction from global stream objects (std::cout, std::cin, std::cerr, and std::clog) is thread-safe.

Does CERR print to console?

cerr is an object of ostream class. It is declared in iostream header file. Used to print the information or error to the console.

Is STD cout synchronized?

It is worth mentioning that the std::cout calls in the main program do not introduce a data race and, therefore, need not be synchronized. The output happens before or after the output of the threads.

Is STD CERR buffered?

cerr: It is the unbuffered standard error stream that is used to output the errors. This is an object of the ostream class similar to cout. It is unbuffered i.e, it is used when there is a need to display the error message immediately. As there is no buffer so it cannot store the error message to display it later.


1 Answers

As others pointed out, in C++11, std::cout is thread-safe.

However if you use it like

std::cout << 1 << 2 << 3;

with different threads, the output can still be interleaved, since every << is a new function call which can be preceeded by any function call on another thread.

To avoid interleaving without a #pragma omp critical - which would lock everything - you can do the following:

std::stringstream stream; // #include <sstream> for this
stream << 1 << 2 << 3;
std::cout << stream.str();

The three calls writing 123 to the stream are happening in only one thread to a local, non-shared object, therefore aren't affected by any other threads. Then, there is only one call to the shared output stream std::cout, where the order of items 123 is already fixed, therefore won't get messed up.

like image 156
stefan Avatar answered Sep 28 '22 04:09

stefan