异步记录器线程安全



我写了一个简单的记录器,我有问题。

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,并发布了它并发布它最后。

最新更新