Threadsafe日志记录

Bjö*_*lex 7 c++ logging streambuf

我想实现一个简单的类来从多个线程进行日志记录.这样的想法是,每个想要记录东西的对象都会收到一个ostream-object,它可以使用通常的操作符来写消息.所需的行为是,在刷新流时将消息添加到日志中.这样,消息不会被来自其他线程的消息中断.我想避免使用临时字符串流来存储消息,因为这会使大多数消息至少是twoliners.正如我所看到的,实现这一目标的标准方法是实现我自己的streambuffer,但这看起来非常麻烦且容易出错.有更简单的方法吗?如果没有,你知道关于自定义streambufs的好文章/指南/指南吗?

提前致谢,

Space_C0wbo0y

更新:

由于它似乎工作,我添加了自己的答案.

Lau*_*ble 5

看看log4cpp ; 他们有多线程支持.它可以节省您的时间.


Bjö*_*lex 1

因此,我查看了Boost.IOstreams,得出的结论如下:

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;
    }
};
Run Code Online (Sandbox Code Playgroud)

TestSink可用于创建流缓冲区(请参阅stream_buffer-template)。每个线程都会收到它自己的 实例TestSink,但所有线程TestSinks都会写入同一个日志。TestSink使用如下:

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;
Run Code Online (Sandbox Code Playgroud)

这里重要的事实是,TestSink.write仅当流被刷新(std::endlstd::flush)时,或者当实例的内部缓冲区stream_buffer已满时(默认缓冲区大小不能容纳 40000 个字符,所以我将其初始化为 50000),才会调用它。在此程序中,TestSink.write只调用一次(输出太长,无法在此处发布)。这样我就可以使用正常格式的流 IO 编写日志消息,而无需任何临时变量,并且可以确保,当我刷新流时,该消息会被完整地发布到日志中。

我将改天再讨论这个问题,以防有我没有考虑到的不同建议/问题。