我写了一个简单的记录器,我有问题。
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;
由于操作员的方式,输出交错了已实施。我如何能够自然使用&lt;&lt;并且它本质上是原子质,所以而不是
你好2再见1
我们保证获得
你好1 再见2
预先感谢。那里是否有银弹或需要新方法?
谢谢
g
使用助手对象。
更改现有的<<
超载方法以返回辅助对象,例如:
template<typename T>
loggerHelper operator<<(const T& t)
{
return loggerHelper{} << t;
}
您的loggerHelper
类必须具有以下属性:
其构造函数应获取sutex。并且击构函数将解锁静音。经常运行的RAII设计模式,但还有一个额外的扭曲:
对象必须正确,并且准确地实现了移动语义。移动从对象实例将不会释放上述静音,而移动的对象将负责。复制构造函数和分配运算符必须为
delete
d。使用
std::cout
并返回*this
,对象实现了"真实"<<
操作员过载。这将触发移动语义,并将声的"热马铃薯"传递到下一个<<
操作员调用中,或者如果没有,则最终销毁了路线最终的助手班级实例。
如果所有这些步骤都正确完成,那么我预计最终结果将是MATER logger
对象上的MUTEX,并且在所有雏菊链的<<
操作员都履行其职责之前,不会发布一次。p>第一个<<
操作员被上面的原始<<
操作员启动,并且它们都被Helper对象的<<
操作员重载进行处理,而Move Sentics则保留了基础的Mutex Lock,并发布了它并发布它最后。