所以我有这样的日志类:
#include <iostream>
#include <sstream>
#include <boost/circular_buffer.hpp>
#include <boost/foreach.hpp>
class FlushInternal;
class Log
{
public:
static FlushInternal* endl;
Log(int log_length)
{
i = 0;
messages_buffer = new boost::circular_buffer<std::string>(log_length);
}
template <class T>
Log &operator<<(const T &v)
{
current_message << v;
return *this;
}
Log &operator<<(std::ostream&(*f)(std::ostream&))
{
current_message << *f;
return *this;
}
Log &operator<<(FlushInternal*)
{
++i;
messages_buffer->push_back(current_message.str());
clean_stringstream(current_message);
is_filled();
return *this;
}
boost::circular_buffer<std::string> *messages_buffer;
private:
int i;
std::stringstream current_message;
void is_filled()
{
if (i >= messages_buffer->capacity())
{
i = 0;
BOOST_FOREACH(std::string s, *messages_buffer)
{
std::cout << ++i << ": " << s << " ;" << std::endl;
}
i = 0;
}
}
void clean_stringstream(std::stringstream &message)
{
message.flush();
message.clear();
message.seekp(0);
message.str("");
}
};
FlushInternal* Log::endl = 0;
我可以像这样使用它:
#include <log.h>
int main()
{
Log l(2);
l << "message one: " << 1 << Log::endl;
l << "message two:" << " " << 2 << Log::endl;
l << "message " << "three: " << 3 << Log::endl;
l << "message" << " " << "four: " << 4 << Log::endl;
std::cin.get();
}
这将输出:
1: message one: 1 ;
2: message two: 2 ;
1: message three: 3 ;
2: message four: 4 ;
正如您所看到的,我可以在每条日志消息中拥有尽可能多的<<
。我希望能够同时使用来自多个线程的Log
类的一个实例。所以我会有类似的东西(编译,运行但没有任何痕迹的伪代码。):
#include <boost/thread.hpp>
#include <log.h>
Log *l;
void fun_one()
{
*l << "message one: " << 1 << Log::endl;
*l << "message two:" << " " << 2 << Log::endl;
}
void fun_two()
{
*l << "message " << "three: " << 3 << Log::endl;
*l << "message" << " " << "four: " << 4 << Log::endl;
}
int main()
{
l = new Log(2);
boost::thread(fun_one);
boost::thread(fun_two);
std::cin.get();
}
因此,您可以看到我希望将消息插入到多线程函数的日志中。我想知道 - 如何让我的日志cclass支持这个?
答案 0 :(得分:3)
这是一种方法:
http://drdobbs.com/cpp/201804215
每次执行日志记录时,它基本上都会创建一个新的ostringstream
对象,从而使其成为线程安全的。我不能说我热衷于此,因为它对我来说似乎有些笨拙。
您可能会查看Qt日志记录类,因为它们支持<< operator
,但我不确定线程安全性。
答案 1 :(得分:3)
由木马相关的方法几乎是规范的方法。基本上为最左边的&lt;&lt;&lt;&lt;&lt;&lt;&lt;运算符,累积所有内容,并在析构函数中为临时事物输出消息。
唯一的问题是这个累加器的确切机制。该示例使用ostringstream
,但我已经看到ofstream
也用于直接使用的日志文件(需要锁定以确保输出最终在一行上)。
在某些平台上创建ostringstreams
相对昂贵,因为他们可能需要锁定和复制一些与内部语言环境相关的内容。您也可以重新实现&lt;&lt;有趣的类型的运算符,但我首先测试ostringstream方法。
有用的优化是在构造临时点时确定是否将发出跟踪(例如,是否在该特定级别启用跟踪),并且在这种情况下根本不创建临时的内容 - 所有插入操作都是no-ops。