qDebug()
and std::cout
are considered not to be thread safe since their docs do not mention anything regarding thread safety.
Which are thread safe printing syntaxes in C++, and Qt?
qDebug()
and std::cout
are considered not to be thread safe since their docs do not mention anything regarding thread safety.
Which are thread safe printing syntaxes in C++, and Qt?
Use an output method that locks a mutex before writing. That way only one thread will write at a time.
#include <iostream>
#include <ostream>
#include <sstream>
#include <mutex>
class Logger {
public:
// destructor is called when output is collected and
// the temporary Logger() dies (after the ";").
~Logger() {
Logger::mutex_.lock(); // make sure I am the only one writing
std::cout << buffer_.str(); // write
std::cout << std::flush; // push to output
Logger::mutex_.unlock(); // I am done, now other threads can write
}
// funny construct you need to chain logs with "<<" like
// in std::cout << "var = " << var;
template <typename T>
Logger &operator<<(T input) {
buffer_ << input;
return *this;
}
private:
// collect the output from chained << calls
std::ostringstream buffer_;
// mutex shared between all instances of Logger
static std::mutex mutex_;
};
// define the static variable. This line must be in one .cpp file
std::mutex Logger::mutex_;
int main()
{
Logger() << "Hello" << " " << "World\n";
Logger() << 123 << "test\n";
return 0;
}
Both are thread safe in the sense that they will not cause your program to crash. Also the output is safe in the sense that all characters sent to the stream will be printed to their intentional value, e.g.
Thread A sends: {a,b,c,d}
Thread B sends: {1,2,3,4}
A valid output can be {a,b,1,2,3,c,d,4} but you will never see a character not from that set e.g. {m}.
In order to serialize your output you should use mutual exclusion the least through some globally accessible mechanism.
e.g. a simple class may well do that
class printsafe{
private:
typedef std::mutex t_lock;
static t_lock l_print;
public:
static void print(std::string const & s}
{
std::lock_guard<printsafe::t_lock> l;
std::cout << s ; // or qDebug(s.c_str());
}
};
Now your output will be either {abcd1234} or {1234abcd} given that
thread A sends: abcd
thread B sends: 1234