[英]async logger thread safe
我写了一个简单的记录器,我有一个问题。
pthread_mutex_t l_mutex = PTHREAD_MUTEX_INITIALIZER;
class logger
{
public:
logger() { }
template<typename T>
logger& operator<<(const T& t)
{
pthread_mutex_lock(&l_mutex);
std::cout << t << std::flush;
pthread_mutex_unlock(&l_mutex);
return *this;
}
protected:
};
static const unsigned char endline = '\n';
static logger log;
然而,当我从两个线程使用记录器时,它会做它不应该做的事情。 调用;
主题#1
log << "Hello " << 1;
主题#2
log << "Goodbye " << 2;
由于 operator<< 的实现方式,输出被交错。 我如何才能自然地使用 << 并且让它本质上是原子的,而不是
你好 2 再见 1
我们保证得到
你好 1 再见 2
提前致谢。 是否有灵丹妙药或需要新方法?
谢谢
G
使用辅助对象。
更改现有的<<
重载方法以返回辅助对象,例如:
template<typename T>
loggerHelper operator<<(const T& t)
{
return loggerHelper{} << t;
}
您的loggerHelper
类必须具有以下属性:
它的构造函数应该获取互斥锁。 析构函数将解锁互斥锁。 普通的 RAII 设计模式,但有一个额外的扭曲:
对象必须正确且准确地实现移动语义。 移出对象实例不会释放前面提到的互斥锁,移到对象将对此负责。 复制构造函数和赋值运算符必须是delete
d。
该对象使用std::cout
实现“真正的” <<
运算符重载并返回*this
。 这将触发移动语义,并将释放互斥锁的“烫手山芋”传递给下一个<<
运算符调用,或者如果没有,则最终销毁路尽头助手类实例。
如果所有这些步骤都正确完成,那么我希望最终结果将是主logger
对象上的互斥锁被获取一次,并且在所有菊花链<<
运算符完成其职责之前不会释放。
第一个<<
运算符由上面的原始<<
运算符启动,并且它们都被真正地处理,由助手对象的<<
运算符重载,移动语义负责保留底层互斥锁,并释放它在末尾。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.