I want to implement a simple class for logging from multiple threads. The idea there is, that each object that wants to log stuff, receives an ostream-object that it can write messages to using the usual operators. The desired behaviour is, that the messages are added to the log when the stream is f开发者_如何学Clushed. This way, messages will not get interrupted by messages from other threads. I want to avoid using a temporary stringstream to store the message, as that would make most messages at least twoliners. As I see it, the standard way of achieving this would be to implement my own streambuffer, but this seems very cumbersome and error-prone. Is there a simpler way to do this? If not, do you know a good article/howto/guide on custom streambufs?
Thanks in advance,
Space_C0wbo0y
UPDATE:
Since it seems to work I added my own answer.
Take a look at log4cpp; they have a multi-thread support. It may save your time.
So, I took a look at Boost.IOstreams and here's what I've come up with:
class TestSink : public boost::iostreams::sink {
public:
std::streamsize write( const char * s, std::streamsize n ) {
std::string message( s, n );
/* This would add a message to the log instead of cout.
The log implementation is threadsafe. */
std::cout << message << std::endl;
return n;
}
};
TestSink
can be used to create a stream-buffer (see stream_buffer-template). Every thread will receive it's own instance of TestSink
, but all TestSinks
will write to the same log. TestSink
is used as follows:
TestSink sink;
boost::iostreams::stream_buffer< TestSink > testbuf( sink, 50000 );
std::ostream out( &testbuf );
for ( int i = 0; i < 10000; i++ )
out << "test" << i;
out << std::endl;
The important fact here is, that TestSink.write
is only called when the stream is flushed (std::endl
or std::flush
), or when the internal buffer of the stream_buffer
instance is full (the default buffer size cannot hold 40000 chars, so I initalize it to 50000). In this program, TestSink.write
is called exactly once (the output is too long to post here). This way I can write logmessage using normal formatted stream-IO without any temporary variables and be sure, that the message is posted to the log in one piece when I flush the stream.
I will leave the question open another day, in case there are different suggestions/problems I have not considered.
You think log4cpp is too heavy and you reach for Boost.IOStreams instead? Huh?
You may wish to consider logog. It's thread-safe for POSIX, Win32 and Win64.
Re. your own response. If you are using this for error logging and you program crashes before flushing your stream then you logging is a bit useless isn't it?
精彩评论