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?
Note: This answer is pre-C++20 so it does not use
std::osyncstreamwith its separate buffering, but uses a lock instead.I guess you could implement your own class which wraps
coutand associates a mutex with it. Theoperator <<of that new class would do three things:<<for the wrapped stream and the passed argumentThis different class would keep the lock and delegate operator
<<to the wrapped stream. The destructor of that second class would eventually destroy the lock and release the mutex.So any output you write as a single statement, i.e. as a single sequence of
<<invocations, will be printed atomically as long as all your output goes through that object with the same mutex.Let’s call the two classes
synchronized_ostreamandlocked_ostream. Ifsync_coutis an instance ofsynchronized_ostreamwhich wrapsstd::cout, then the sequencewould result in the following actions:
synchronized_ostream::operator<<would aquire the locksynchronized_ostream::operator<<would delegate the printing of “Hello, ” tocoutoperator<<(std::ostream&, const char*)would print “Hello, “synchronized_ostream::operator<<would construct alocked_ostreamand pass the lock to thatlocked_ostream::operator<<would delegate the printing ofnametocoutoperator<<(std::ostream&, std::string)would print the namecouthappens for the exclamation point and the endline manipulatorlocked_ostreamtemporary gets destructed, the lock is released