背景: 我正在尝试优化日志系统,以便它使用内存映射文件。我需要提供一个类似std :: ostream的接口,以便日志记录系统可以写入该内存。 我已经识别出std :: strstream(虽然不赞成使用),boost :: iostreams :: basic_array_sink可以满足我的需求。
现在我希望记录循环,这意味着当输出指针靠近内存块的末尾时,它应该再次从头开始。 我的问题是,为了实现这一特定行为,最佳起点是什么。
我对std :: iostreams类层次结构感到不知所措,并没有像现在这样掌握所有内部工作原理。 我不确定我是否应该/需要从ostream,streambuf或两者中获得? 这些是为了衍生出来的吗?
或者使用boost:iostreams,我是否需要编写自己的Sink?
编辑: 以下尝试编译并生成预期输出:
class rollingstreambuf : public std::basic_streambuf<TCHAR>
{
public:
typedef std::basic_streambuf<TCHAR> Base;
rollingstreambuf(Base::char_type* baseptr, size_t size)
{
setp(baseptr, baseptr + size);
}
protected:
virtual int_type overflow (int_type c)
{
// reset position to start of buffer
setp(pbase(), epptr());
return putchar(c);
}
virtual std::streamsize xsputn (const char* s, std::streamsize n)
{
if (n >= epptr() - pptr())
// reset position to start of buffer
setp(pbase(), epptr());
return Base::xsputn(s, n);
}
};
char buffer[100];
rollingstreambuf buf(buffer, sizeof(buffer));
std::basic_ostream<TCHAR> out(&buf);
for (int i=0; i<10; i++)
{
out << "Mumblemumble " << i << '\n';
}
out << std::ends; //write terminating NULL char
打印缓冲区给出:
Mumblemumble 6
Mumblemumble 7
Mumblemumble 8
Mumblemumble 9
(确认已发生翻车)
它的作用是使streambuf使用提供的缓冲区作为循环输出缓冲区(放置区域),而不会在输出序列(流)中推进缓冲区窗口。 (使用http://en.cppreference.com/w/cpp/io/basic_streambuf)
中的术语现在我对这种实现的稳健性和质量感到非常不确定。请查看并评论。
答案 0 :(得分:2)
这是一种有效的方法。 overflow()
应该返回:
traits :: eof()或在函数失败时抛出异常。否则,返回traits :: eof()以外的一些值来表示成功。
E.g:
virtual int_type overflow (int_type c)
{
// reset position to start of buffer
setp(pbase(), epptr());
return traits::not_eof(c);
}
xsputn()
应该将序列的开头写入缓冲区的末尾,然后将其余的序列倒回并写入缓冲区的前面。您可以使用xsputn()
的默认实现来为每个字符调用sputc(c)
,然后在缓冲区已满时调用overflow()
。