title: Logger class using streams [multithreaded]
body: <p>I have a logging class in C++. It's a singleton with multithreading support.</p>
  
  <p>What I wanted to achieve (and mainly did):</p>
  
  <ul>
  <li>have a generic logger class</li>
  <li>singleton</li>
  <li>use it with stream insertion operator not as a function call</li>
  </ul>
  
  <p>The class writes in a std::stringstream and on std::endl it flushes the std::stringstream content to file. A big drawback is that std::endl is required once and onlny once per call for everything to work correctly in a multithreading app. <em>not sure if it's a good approach, but it's ok for now and in my case I can go with this drawback</em></p>
  
  <p>My problem is that a call to std::setfill() when logging will deadlock. It seems that this call is not sent to my Logger class and is executed outside its critical section.</p>
  
  <p>Can I achieve this? A logger class with full support for manips?</p>
  
  <p><strong>Log Calls</strong></p>
  
  <pre><code>LOGI &lt;&lt; "Some message " &lt;&lt; aVariable &lt;&lt; std::endl;                // OK
  LOGI &lt;&lt; std::setw(20) &lt;&lt; var &lt;&lt; std::endl                         // OK
  LOGI &lt;&lt; std::setfill('-') &lt;&lt; std::setw(50) &lt;&lt; var &lt;&lt; std::endl;   // NOT OK because of setfill() call !!!!
  </code></pre>
  
  <p><strong>Class Sample code</strong></p>
  
  <pre><code>#define LOGFATAL Logger::GetLogger(LOGLEVEL_FATAL,      __FUNCTION__)
  #define LOGE     Logger::GetLogger(LOGLEVEL_ERROR,      __FUNCTION__)
  #define LOGW     Logger::GetLogger(LOGLEVEL_WARN,       __FUNCTION__)
  #define LOGI     Logger::GetLogger(LOGLEVEL_INFO,       __FUNCTION__)
  #define LOGD     Logger::GetLogger(LOGLEVEL_DEBUG,      __FUNCTION__)
  #define LOGV     Logger::GetLogger(LOGLEVEL_VERBOSE,    __FUNCTION__)
  
  class Logger
  {
  public:
      static void Initialize(const std::string&amp; _logFile, const std::string&amp; _logLevel)
      {
          isInitialized = true;
          logFileName = _logFile;
          logLevel = GetLogLevel(_logLevel);
      }
      static Logger&amp; GetLogger(LogLevel l, const std::string&amp; funcName)
      {
          if(isInitialized)
              csFile-&gt;lock();
  
          msgLogLevel = l;
          functionName = funcName;
          return GetLogger();
      }
  
      typedef std::ostream&amp;  (*ManipFn)(std::ostream&amp;);
      typedef std::ios_base&amp; (*FlagsFn)(std::ios_base&amp;);
  
      template&lt;class T&gt;
      Logger&amp; operator&lt;&lt;(const T&amp; output)
      {
          if (!isInitialized)
              return *this;
  
          m_stream &lt;&lt; output;
          return *this;
      }
  
      Logger&amp; operator&lt;&lt;(const ManipFn manip)
      {
          if (!isInitialized)
              return *this;
  
          manip(m_stream);
  
          if (manip == static_cast&lt;ManipFn&gt;(std::flush) ||
              manip == static_cast&lt;ManipFn&gt;(std::endl))
          {
              // flush the stream and unlock the mutex
              this-&gt;flush();
              csFile-&gt;unlock();
          }
          return *this;
      }
  
      Logger&amp; operator&lt;&lt;(const FlagsFn manip) /// setiosflags, resetiosflags
      {
          manip(m_stream);
          return *this;
      }
  ...
      static Logger&amp; GetLogger()
      {
          static Logger instance;
          return instance;
      }
  
  
  </code></pre>
  
  <p>Let me know if more information is needed</p>