为日志记录重载 << 运算符的设计的潜在问题

Potential problems with a design that overloads << operator for logging

我想写一个 class 可以像 std::cout 使用 << 运算符一样使用。我希望能够在使用一系列 << 运算符的代码段的开头获得互斥锁,并在语句结束时释放该互斥锁。

例如:

logger << "Information blah "<< 1;

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

这些 classes 的设计是否存在重大问题?我知道有大量的日志记录库,我只是在尝试一种在一系列 << 运算符开始时维护互斥锁并在结束时释放互斥锁的方法。

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;

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

相反,你为什么不想办法在没有锁的情况下准备要记录的 information/string(例如,进入 function/scope 本地或线程本地 object/string)然后一次记录整个 information/string,保持同步部分尽可能短。