繁体   English   中英

异步记录器线程安全

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM