Search code examples
c++c++11loggingmutexflush

How to flush a log message and unlock a mutex automatically in C++?


I wrote this logger. It works fine, but there is something I have not been able to do.

uLOG(warning) << "Test log message " << 123 << uLOGE;

uLOG locks a C++11 mutex and starts writing on a file stream.
uLOGE flushes the stream and unlocks the mutex.

I would like to get the same result with this syntax:

uLOG(warning) << "Test log message " << 123;

so I would like the flush and the unlock to be called automatically at the end of the line.

Which is a possible way to do it?

  • I tried setting the ios::unitbuf flag, but this forces a flush for every << operator, not ideal for an SSD wearing. And it does not unlock the mutex.
  • I tried defining a temporary object in uLOG whose destructor would flush and unlock, but that forces to put the log line in its own code block: { uLOG(warning) << 123; }

Reference


Solution

  • You need to redesign your logging framework, so that uLOG is a class that you instantiate, and whose destructor does the work of your uLOGE macro.


    Very simple example:

    struct uLOG
    {
        uLOG(std::string const& type)
        {
            std::cout << "Log: " << type << " - ";
        }
    
        template<typename T>
        uLOG& operator<<(T const& output)
        {
            std::cout << output;
            return *this;
        }
    
        ~uLOG()
        {
            std::cout << " (end of log)" << std::endl;
        }
    };
    
    // ...
    uLOG("warning") << "log message" << 123;
    

    The above, in a suitable program, should print

    Log: warning - log message123 (end of log)
    

    This solution should not require the use of braces, so could be used in a single-statement un-braced if or loop.