Da gibt's sicher viele Möglichkeiten, ich würde da mal spontan meinen alten Musterstreambuf reaktivieren und in dessen Overflowfunktion die Lognachricht ausgeben:
#include <streambuf>
#include <ios>
#include <thread>
#include <sstream>
class seppjs_thread_logger_streambuf : public std::streambuf
{
public:
seppjs_thread_logger_streambuf(std::ios& in) : in(in), buf (in.rdbuf()), newline(true)
{
in.rdbuf(this);
}
~seppjs_thread_logger_streambuf()
{
in.rdbuf(buf);
}
seppjs_thread_logger_streambuf(const seppjs_thread_logger_streambuf&) = delete;
seppjs_thread_logger_streambuf& operator=(const seppjs_thread_logger_streambuf&) = delete;
private:
std::ios& in;
std::streambuf* buf;
bool newline;
protected:
virtual int_type overflow(int_type c)
{
if(newline)
{
std::stringstream message;
message << "Task " << std::this_thread::get_id() << ": ";
buf->sputn(message.str().data(), message.str().size());
newline = false;
}
if (traits_type::eq_int_type(c, traits_type::to_int_type('\n')))
newline = true;
buf->sputc(c);
return c;
}
};
// Beispielanwendung
#include <iostream>
void function()
{
std::cout << "Blah\nBlupp\nBäh\n";
}
int main()
{
seppjs_thread_logger_streambuf foo(std::cout);
std::thread t1(function), t2(function);
t1.join();
t2.join();
}
edit: ideone-Link: http://ideone.com/i6YeBH
Dazu sei noch angemerkt, dass printf auf manchen Systemen (mindestens solchen mit glibc) garantiert threadsicher ist. Ausgaben über std::cout aber nicht*! Dies ist daher auch eine gute Gelegenheit, noch einen Mutex vor die Ausgabe zu schalten. Das überlasse ich aber dem geneigten Leser zur Übung.
*: In dem Sinne, dass Streamausgabefunktionen zwar reentrant sind, aber dass gleichzeitige Ausgaben dann eventuell wild miteinander verquirlt werden. Bei printf ist bei der glibc hingegen garantiert, dass ein printf komplett abgearbeitet wird, bevor das nächste dran kommt.