【问题标题】:Potential problems with a design that overloads << operator for logging重载 << 运算符以进行日志记录的设计的潜在问题
【发布时间】:2015-01-03 20:51:32
【问题描述】:

我想编写一个可以类似于std::cout 使用&lt;&lt; 运算符的类。我希望能够在使用一系列 &lt;&lt; 运算符的代码段的开头获得一个互斥体,并在语句末尾释放该互斥体。

例如:

logger << "Information blah "<< 1;

如果没有锁,在多线程操作中,事情可能会在“Information blah”和 1 之间交错。

这些类的设计是否存在一些重大问题?我知道有大量的日志库,我只是想在一系列 &lt;&lt; 运算符的开头维护一个互斥锁并在最后释放互斥锁。

class Logger;

class LockedLogger
{
    public:
        LockedLogger(Logger & logger):logger_(logger),lock_(new std::lock_guard<std::mutex>(logger.outputMutex_)) {};

        template<typename T>
        const LockedLogger & operator <<(T t) const{//Logging Code.}    
    private:
        LockedLogger & logger_;
        std::shared_ptr<std::lock_guard<std::mutex> > lock_;
};


class Logger
{
    public:
        Logger();

        template<typename T>
        LockedLogger operator << (T t){return LockedLogger(*this) << t;}

    private:
        std::mutex outputMutex_;

        friend class LockedLogger;
};
Logger logger;

【问题讨论】:

  • 是的。当然,实现记录器可能有更简单的方法。
  • 嗯,它有效吗?如果不是,问题是什么?如果是这样,你应该在Code Review
  • 似乎工作正常(我发现有时看起来工作的东西在某些情况下实际上并不工作方法)。谢谢,我不知道存在代码审查。将在那里发布。

标签: c++ multithreading logging


【解决方案1】:

如果您选择使用锁定的记录器,那么当一个线程正在记录并可能准备要记录的信息/字符串时,您将停止其他线程。

相反,您为什么不想办法在没有锁定的情况下准备要记录的信息/字符串(例如,进入函数/范围本地或线程本地对象/字符串),然后记录整个信息/字符串同时,保持同步部分尽可能短。

【讨论】:

  • +1 获取实用方法。您的建议遵循职责分离的原则。字符串格式化程序很容易编写。
  • 这很容易做到:我只需要继续连接项目,然后在 LockedLogger 超出范围时获取锁写入并释放锁。除此之外,
  • @rileymat:不;事实上,这是一种常见的模式。你说的是代理对象。
  • 有时,可以将指向对象的指针发送/排队到单独的记录器线程,然后在它到达时调用 serialise() 方法。这几乎消除了原始线程的所有负载,并将锁定时间减少到复制指针所需的时间。当然,由于生命周期、可变性等原因,这并不总是可能的,但我想我还是应该提一下,如果只是为了惹恼 Loungers。
猜你喜欢
  • 2012-01-12
  • 1970-01-01
  • 2022-01-21
  • 2013-08-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-03
  • 1970-01-01
  • 2011-09-24
相关资源
最近更新 更多