A line-based thread-safe std::cerr for C++










3















What is the easiest way to create my own std::cerr so that it is line-by-line thread-safe.



I am preferably looking for the code to do it.



What I need is so that a line of output (terminated with std::endl) generated by one thread stays as a line of output when I actually see it on my console (and is not mixed with some other thread's output).




Solution: std::cerr is much slower than cstdio. I prefer using fprintf(stderr, "The message") inside of a CriticalSectionLocker class whose constructor acquires a thread-safe lock and the destructor releases it.










share|improve this question



















  • 1





    How do you imagine creating a thread local buffer "hooked" into std::cerr would reduce buffering over a thread local buffer "outside", then writing full lines into std::cerr? A buffer's a buffer. std::ostringstream is a typical general purpose approach for this.

    – Tony Delroy
    Dec 15 '10 at 3:46






  • 3





    Are you by any chance looking for a thread-safe logging library?

    – yasouser
    Dec 15 '10 at 3:47






  • 1





    I recently learnt about the log4cpp project (log4cpp.sourceforge.net). Not sure whether it provides what you are looking for!?!? Maybe worthwhile to check it out.

    – yasouser
    Dec 15 '10 at 4:01











  • your own iostream cerr implementation is potentially much more buggy than using a well-tested library like log4cpp

    – Ken Bloom
    Dec 15 '10 at 4:20















3















What is the easiest way to create my own std::cerr so that it is line-by-line thread-safe.



I am preferably looking for the code to do it.



What I need is so that a line of output (terminated with std::endl) generated by one thread stays as a line of output when I actually see it on my console (and is not mixed with some other thread's output).




Solution: std::cerr is much slower than cstdio. I prefer using fprintf(stderr, "The message") inside of a CriticalSectionLocker class whose constructor acquires a thread-safe lock and the destructor releases it.










share|improve this question



















  • 1





    How do you imagine creating a thread local buffer "hooked" into std::cerr would reduce buffering over a thread local buffer "outside", then writing full lines into std::cerr? A buffer's a buffer. std::ostringstream is a typical general purpose approach for this.

    – Tony Delroy
    Dec 15 '10 at 3:46






  • 3





    Are you by any chance looking for a thread-safe logging library?

    – yasouser
    Dec 15 '10 at 3:47






  • 1





    I recently learnt about the log4cpp project (log4cpp.sourceforge.net). Not sure whether it provides what you are looking for!?!? Maybe worthwhile to check it out.

    – yasouser
    Dec 15 '10 at 4:01











  • your own iostream cerr implementation is potentially much more buggy than using a well-tested library like log4cpp

    – Ken Bloom
    Dec 15 '10 at 4:20













3












3








3


2






What is the easiest way to create my own std::cerr so that it is line-by-line thread-safe.



I am preferably looking for the code to do it.



What I need is so that a line of output (terminated with std::endl) generated by one thread stays as a line of output when I actually see it on my console (and is not mixed with some other thread's output).




Solution: std::cerr is much slower than cstdio. I prefer using fprintf(stderr, "The message") inside of a CriticalSectionLocker class whose constructor acquires a thread-safe lock and the destructor releases it.










share|improve this question
















What is the easiest way to create my own std::cerr so that it is line-by-line thread-safe.



I am preferably looking for the code to do it.



What I need is so that a line of output (terminated with std::endl) generated by one thread stays as a line of output when I actually see it on my console (and is not mixed with some other thread's output).




Solution: std::cerr is much slower than cstdio. I prefer using fprintf(stderr, "The message") inside of a CriticalSectionLocker class whose constructor acquires a thread-safe lock and the destructor releases it.







c++ multithreading iostream stderr subclassing






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 15 '18 at 11:37









vallismortis

3,684104366




3,684104366










asked Dec 15 '10 at 3:41









unixman83unixman83

4,66895391




4,66895391







  • 1





    How do you imagine creating a thread local buffer "hooked" into std::cerr would reduce buffering over a thread local buffer "outside", then writing full lines into std::cerr? A buffer's a buffer. std::ostringstream is a typical general purpose approach for this.

    – Tony Delroy
    Dec 15 '10 at 3:46






  • 3





    Are you by any chance looking for a thread-safe logging library?

    – yasouser
    Dec 15 '10 at 3:47






  • 1





    I recently learnt about the log4cpp project (log4cpp.sourceforge.net). Not sure whether it provides what you are looking for!?!? Maybe worthwhile to check it out.

    – yasouser
    Dec 15 '10 at 4:01











  • your own iostream cerr implementation is potentially much more buggy than using a well-tested library like log4cpp

    – Ken Bloom
    Dec 15 '10 at 4:20












  • 1





    How do you imagine creating a thread local buffer "hooked" into std::cerr would reduce buffering over a thread local buffer "outside", then writing full lines into std::cerr? A buffer's a buffer. std::ostringstream is a typical general purpose approach for this.

    – Tony Delroy
    Dec 15 '10 at 3:46






  • 3





    Are you by any chance looking for a thread-safe logging library?

    – yasouser
    Dec 15 '10 at 3:47






  • 1





    I recently learnt about the log4cpp project (log4cpp.sourceforge.net). Not sure whether it provides what you are looking for!?!? Maybe worthwhile to check it out.

    – yasouser
    Dec 15 '10 at 4:01











  • your own iostream cerr implementation is potentially much more buggy than using a well-tested library like log4cpp

    – Ken Bloom
    Dec 15 '10 at 4:20







1




1





How do you imagine creating a thread local buffer "hooked" into std::cerr would reduce buffering over a thread local buffer "outside", then writing full lines into std::cerr? A buffer's a buffer. std::ostringstream is a typical general purpose approach for this.

– Tony Delroy
Dec 15 '10 at 3:46





How do you imagine creating a thread local buffer "hooked" into std::cerr would reduce buffering over a thread local buffer "outside", then writing full lines into std::cerr? A buffer's a buffer. std::ostringstream is a typical general purpose approach for this.

– Tony Delroy
Dec 15 '10 at 3:46




3




3





Are you by any chance looking for a thread-safe logging library?

– yasouser
Dec 15 '10 at 3:47





Are you by any chance looking for a thread-safe logging library?

– yasouser
Dec 15 '10 at 3:47




1




1





I recently learnt about the log4cpp project (log4cpp.sourceforge.net). Not sure whether it provides what you are looking for!?!? Maybe worthwhile to check it out.

– yasouser
Dec 15 '10 at 4:01





I recently learnt about the log4cpp project (log4cpp.sourceforge.net). Not sure whether it provides what you are looking for!?!? Maybe worthwhile to check it out.

– yasouser
Dec 15 '10 at 4:01













your own iostream cerr implementation is potentially much more buggy than using a well-tested library like log4cpp

– Ken Bloom
Dec 15 '10 at 4:20





your own iostream cerr implementation is potentially much more buggy than using a well-tested library like log4cpp

– Ken Bloom
Dec 15 '10 at 4:20












5 Answers
5






active

oldest

votes


















3














Here's a thread safe line based logging solution I cooked up at some point. It uses boost mutex for thread safety. It is slightly more complicated than necessary because you can plug in output policies (should it go to a file, stderr, or somewhere else?):



logger.h:



#ifndef LOGGER_20080723_H_
#define LOGGER_20080723_H_

#include <boost/thread/mutex.hpp>
#include <iostream>
#include <cassert>
#include <sstream>
#include <ctime>
#include <ostream>

namespace logger
namespace detail

template<class Ch, class Tr, class A>
class no_output
private:
struct null_buffer
template<class T>
null_buffer &operator<<(const T &)
return *this;

;
public:
typedef null_buffer stream_buffer;

public:
void operator()(const stream_buffer &)

;

template<class Ch, class Tr, class A>
class output_to_clog
public:
typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
public:
void operator()(const stream_buffer &s)
static boost::mutex mutex;
boost::mutex::scoped_lock lock(mutex);
std::clog << now() << ": " << s.str() << std::endl;


private:
static std::string now()
char buf[64];
const time_t tm = time(0);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tm));
return buf;


;

template<template <class Ch, class Tr, class A> class OutputPolicy, class Ch = char, class Tr = std::char_traits<Ch>, class A = std::allocator<Ch> >
class logger
typedef OutputPolicy<Ch, Tr, A> output_policy;
public:
~logger()
output_policy()(m_SS);

public:
template<class T>
logger &operator<<(const T &x)
m_SS << x;
return *this;

private:
typename output_policy::stream_buffer m_SS;
;


class log : public detail::logger<detail::output_to_clog>
;


#endif


Usage looks like this:



logger::log() << "this is a test" << 1234 << "testing";


note the lack of a 'n' and std::endl since it's implicit. The contents are buffered and then atomically output using the template specified policy. This implementation also prepends the line with a timestamp since it is for logging purposes. The no_output policy is stricly optional, it's what I use when I want to disable logging.






share|improve this answer






























    2














    This:



    #define myerr(e) CiriticalSectionLocker crit; std::cerr << e << std::endl;


    works on most compilers for the common case of myerr("ERR: " << message << number).






    share|improve this answer

























    • This presumes you don't want to use the << operator for formatting (e.g. cerr << "This log message has been printed " << ntimes << " times." << endl;)

      – Ken Bloom
      Dec 15 '10 at 14:54






    • 2





      Hrm. I'm actually wrong about that, because I forgot temporarily how macros work. All you'd need to do to get formatting is call lerr("This log message has been printed " << ntimes << " times.") and the text substitution would get it right.

      – Ken Bloom
      Dec 15 '10 at 18:53



















    2














    Why not just create a locking class and use it where ever you want to do thread-safe IO?



    class LockIO

    static pthread_mutex_t *mutex;
    public:
    LockIO() pthread_mutex_lock( mutex );
    ~LockIO() pthread_mutex_unlock( mutex );
    ;

    static pthread_mutex_t* getMutex()

    pthread_mutex_t *mutex = new pthread_mutex_t;
    pthread_mutex_init( mutex, NULL );
    return mutex;

    pthread_mutex_t* LockIO::mutex = getMutex();


    Then you put any IO you want in a block:



    std::cout <<"X is " <<x <<std::endl;


    becomes:




    LockIO lock;
    std::cout <<"X is " <<x <<std::endl;






    share|improve this answer
































      2














      If available, osyncstream (C++20) solves this problem:



      #include <syncstream> // C++20

      std::osyncstream tout(std::cout);
      std::osyncstream terr(std::cerr);



      If the above feature is not available, here is a drop-in header file containing two macros for thread-safe writing to std::cout and std::cerr (which must share a mutex in order to avoid interleaving of output). These are based on two other answers, but I have made some changes to make it easy to drop into an existing code base. This works with C++11 and forward.



      I've tested this with 4 threads on a 4-core processor, with each thread writing 25,000 lines per second to tout and occasional output to terr, and it solves the output interleaving problem. Unlike a struct-based solution, there was no measurable performance hit for my application when dropping in this header file. The only drawback I can think of is that since this relies on macros, they can't be placed into a namespace.



      threadstream.h



      #ifndef THREADSTREAM
      #define THREADSTREAM

      #include <iostream>
      #include <sstream>
      #include <mutex>

      #define terr ThreadStream(std::cerr)
      #define tout ThreadStream(std::cout)

      /**
      * Thread-safe std::ostream class.
      *
      * Usage:
      * tout << "Hello world!" << std::endl;
      * terr << "Hello world!" << std::endl;
      */
      class ThreadStream : public std::ostringstream

      public:
      ThreadStream(std::ostream& os) : os_(os)

      // copyfmt causes odd problems with lost output
      // probably some specific flag
      // copyfmt(os);
      // copy whatever properties are relevant
      imbue(os.getloc());
      precision(os.precision());
      width(os.width());
      setf(std::ios::fixed, std::ios::floatfield);


      ~ThreadStream()

      std::lock_guard<std::mutex> guard(_mutex_threadstream);
      os_ << this->str();


      private:
      static std::mutex _mutex_threadstream;
      std::ostream& os_;
      ;

      std::mutex ThreadStream::_mutex_threadstream;

      #endif



      test.cc



      #include <thread>
      #include <vector>
      #include <iomanip>
      #include "threadstream.h"

      void test(const unsigned int threadNumber)

      tout << "Thread " << threadNumber << ": launched" << std::endl;


      int main()

      std::locale mylocale(""); // get global locale
      std::cerr.imbue(mylocale); // imbue global locale
      std::ios_base::sync_with_stdio(false); // disable synch with stdio (enables input buffering)

      std::cout << std::fixed << std::setw(4) << std::setprecision(5);
      std::cerr << std::fixed << std::setw(2) << std::setprecision(2);

      std::vector<std::thread> threads;

      for (unsigned int threadNumber = 0; threadNumber < 16; threadNumber++)

      std::thread t(test, threadNumber);
      threads.push_back(std::move(t));


      for (std::thread& t : threads)

      if (t.joinable())

      t.join();



      terr << std::endl << "Main: " << "Test completed." << std::endl;

      return 0;




      compiling



      g++ -g -O2 -Wall -c -o test.o test.cc
      g++ -o test test.o -pthread



      output



      ./test
      Thread 0: launched
      Thread 4: launched
      Thread 3: launched
      Thread 1: launched
      Thread 2: launched
      Thread 6: launched
      Thread 5: launched
      Thread 7: launched
      Thread 8: launched
      Thread 9: launched
      Thread 10: launched
      Thread 11: launched
      Thread 12: launched
      Thread 13: launched
      Thread 14: launched
      Thread 15: launched

      Main: Test completed.





      share|improve this answer

























      • Awesome, thanks!

        – thc
        Mar 12 at 18:41


















      1














      An improvement (that doesn't really fit in a comment) on the approach in unixman's comment.



      #define LOCKED_ERR 
      if(ErrCriticalSectionLocker crit = ErrCriticalSectionLocker());
      else std::cerr


      Which can be used like



      LOCKED_ERR << "ERR: " << message << endl;


      if ErrCriticalSectionLocker is implemented carefully.



      But, I would personally prefer Ken's suggestion.






      share|improve this answer























      • +1 for creative use of the lifecycle of temporaries. Could you provide an implementation of ErrCriticalSectionLocker, becuase the semantics are very non-trivial?

        – Ken Bloom
        Dec 15 '10 at 14:55












      • Hmm. I see; You can use this method without parenthesis but I see little point in that, since my C (I come from C background) programming style generally calls for parenthesis. Also, ErrCriticalSectionLocker is confusing...

        – unixman83
        Jul 18 '11 at 9:00












      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f4446484%2fa-line-based-thread-safe-stdcerr-for-c%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      3














      Here's a thread safe line based logging solution I cooked up at some point. It uses boost mutex for thread safety. It is slightly more complicated than necessary because you can plug in output policies (should it go to a file, stderr, or somewhere else?):



      logger.h:



      #ifndef LOGGER_20080723_H_
      #define LOGGER_20080723_H_

      #include <boost/thread/mutex.hpp>
      #include <iostream>
      #include <cassert>
      #include <sstream>
      #include <ctime>
      #include <ostream>

      namespace logger
      namespace detail

      template<class Ch, class Tr, class A>
      class no_output
      private:
      struct null_buffer
      template<class T>
      null_buffer &operator<<(const T &)
      return *this;

      ;
      public:
      typedef null_buffer stream_buffer;

      public:
      void operator()(const stream_buffer &)

      ;

      template<class Ch, class Tr, class A>
      class output_to_clog
      public:
      typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
      public:
      void operator()(const stream_buffer &s)
      static boost::mutex mutex;
      boost::mutex::scoped_lock lock(mutex);
      std::clog << now() << ": " << s.str() << std::endl;


      private:
      static std::string now()
      char buf[64];
      const time_t tm = time(0);
      strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tm));
      return buf;


      ;

      template<template <class Ch, class Tr, class A> class OutputPolicy, class Ch = char, class Tr = std::char_traits<Ch>, class A = std::allocator<Ch> >
      class logger
      typedef OutputPolicy<Ch, Tr, A> output_policy;
      public:
      ~logger()
      output_policy()(m_SS);

      public:
      template<class T>
      logger &operator<<(const T &x)
      m_SS << x;
      return *this;

      private:
      typename output_policy::stream_buffer m_SS;
      ;


      class log : public detail::logger<detail::output_to_clog>
      ;


      #endif


      Usage looks like this:



      logger::log() << "this is a test" << 1234 << "testing";


      note the lack of a 'n' and std::endl since it's implicit. The contents are buffered and then atomically output using the template specified policy. This implementation also prepends the line with a timestamp since it is for logging purposes. The no_output policy is stricly optional, it's what I use when I want to disable logging.






      share|improve this answer



























        3














        Here's a thread safe line based logging solution I cooked up at some point. It uses boost mutex for thread safety. It is slightly more complicated than necessary because you can plug in output policies (should it go to a file, stderr, or somewhere else?):



        logger.h:



        #ifndef LOGGER_20080723_H_
        #define LOGGER_20080723_H_

        #include <boost/thread/mutex.hpp>
        #include <iostream>
        #include <cassert>
        #include <sstream>
        #include <ctime>
        #include <ostream>

        namespace logger
        namespace detail

        template<class Ch, class Tr, class A>
        class no_output
        private:
        struct null_buffer
        template<class T>
        null_buffer &operator<<(const T &)
        return *this;

        ;
        public:
        typedef null_buffer stream_buffer;

        public:
        void operator()(const stream_buffer &)

        ;

        template<class Ch, class Tr, class A>
        class output_to_clog
        public:
        typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
        public:
        void operator()(const stream_buffer &s)
        static boost::mutex mutex;
        boost::mutex::scoped_lock lock(mutex);
        std::clog << now() << ": " << s.str() << std::endl;


        private:
        static std::string now()
        char buf[64];
        const time_t tm = time(0);
        strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tm));
        return buf;


        ;

        template<template <class Ch, class Tr, class A> class OutputPolicy, class Ch = char, class Tr = std::char_traits<Ch>, class A = std::allocator<Ch> >
        class logger
        typedef OutputPolicy<Ch, Tr, A> output_policy;
        public:
        ~logger()
        output_policy()(m_SS);

        public:
        template<class T>
        logger &operator<<(const T &x)
        m_SS << x;
        return *this;

        private:
        typename output_policy::stream_buffer m_SS;
        ;


        class log : public detail::logger<detail::output_to_clog>
        ;


        #endif


        Usage looks like this:



        logger::log() << "this is a test" << 1234 << "testing";


        note the lack of a 'n' and std::endl since it's implicit. The contents are buffered and then atomically output using the template specified policy. This implementation also prepends the line with a timestamp since it is for logging purposes. The no_output policy is stricly optional, it's what I use when I want to disable logging.






        share|improve this answer

























          3












          3








          3







          Here's a thread safe line based logging solution I cooked up at some point. It uses boost mutex for thread safety. It is slightly more complicated than necessary because you can plug in output policies (should it go to a file, stderr, or somewhere else?):



          logger.h:



          #ifndef LOGGER_20080723_H_
          #define LOGGER_20080723_H_

          #include <boost/thread/mutex.hpp>
          #include <iostream>
          #include <cassert>
          #include <sstream>
          #include <ctime>
          #include <ostream>

          namespace logger
          namespace detail

          template<class Ch, class Tr, class A>
          class no_output
          private:
          struct null_buffer
          template<class T>
          null_buffer &operator<<(const T &)
          return *this;

          ;
          public:
          typedef null_buffer stream_buffer;

          public:
          void operator()(const stream_buffer &)

          ;

          template<class Ch, class Tr, class A>
          class output_to_clog
          public:
          typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
          public:
          void operator()(const stream_buffer &s)
          static boost::mutex mutex;
          boost::mutex::scoped_lock lock(mutex);
          std::clog << now() << ": " << s.str() << std::endl;


          private:
          static std::string now()
          char buf[64];
          const time_t tm = time(0);
          strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tm));
          return buf;


          ;

          template<template <class Ch, class Tr, class A> class OutputPolicy, class Ch = char, class Tr = std::char_traits<Ch>, class A = std::allocator<Ch> >
          class logger
          typedef OutputPolicy<Ch, Tr, A> output_policy;
          public:
          ~logger()
          output_policy()(m_SS);

          public:
          template<class T>
          logger &operator<<(const T &x)
          m_SS << x;
          return *this;

          private:
          typename output_policy::stream_buffer m_SS;
          ;


          class log : public detail::logger<detail::output_to_clog>
          ;


          #endif


          Usage looks like this:



          logger::log() << "this is a test" << 1234 << "testing";


          note the lack of a 'n' and std::endl since it's implicit. The contents are buffered and then atomically output using the template specified policy. This implementation also prepends the line with a timestamp since it is for logging purposes. The no_output policy is stricly optional, it's what I use when I want to disable logging.






          share|improve this answer













          Here's a thread safe line based logging solution I cooked up at some point. It uses boost mutex for thread safety. It is slightly more complicated than necessary because you can plug in output policies (should it go to a file, stderr, or somewhere else?):



          logger.h:



          #ifndef LOGGER_20080723_H_
          #define LOGGER_20080723_H_

          #include <boost/thread/mutex.hpp>
          #include <iostream>
          #include <cassert>
          #include <sstream>
          #include <ctime>
          #include <ostream>

          namespace logger
          namespace detail

          template<class Ch, class Tr, class A>
          class no_output
          private:
          struct null_buffer
          template<class T>
          null_buffer &operator<<(const T &)
          return *this;

          ;
          public:
          typedef null_buffer stream_buffer;

          public:
          void operator()(const stream_buffer &)

          ;

          template<class Ch, class Tr, class A>
          class output_to_clog
          public:
          typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
          public:
          void operator()(const stream_buffer &s)
          static boost::mutex mutex;
          boost::mutex::scoped_lock lock(mutex);
          std::clog << now() << ": " << s.str() << std::endl;


          private:
          static std::string now()
          char buf[64];
          const time_t tm = time(0);
          strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tm));
          return buf;


          ;

          template<template <class Ch, class Tr, class A> class OutputPolicy, class Ch = char, class Tr = std::char_traits<Ch>, class A = std::allocator<Ch> >
          class logger
          typedef OutputPolicy<Ch, Tr, A> output_policy;
          public:
          ~logger()
          output_policy()(m_SS);

          public:
          template<class T>
          logger &operator<<(const T &x)
          m_SS << x;
          return *this;

          private:
          typename output_policy::stream_buffer m_SS;
          ;


          class log : public detail::logger<detail::output_to_clog>
          ;


          #endif


          Usage looks like this:



          logger::log() << "this is a test" << 1234 << "testing";


          note the lack of a 'n' and std::endl since it's implicit. The contents are buffered and then atomically output using the template specified policy. This implementation also prepends the line with a timestamp since it is for logging purposes. The no_output policy is stricly optional, it's what I use when I want to disable logging.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 15 '10 at 22:08









          Evan TeranEvan Teran

          67.9k19157221




          67.9k19157221























              2














              This:



              #define myerr(e) CiriticalSectionLocker crit; std::cerr << e << std::endl;


              works on most compilers for the common case of myerr("ERR: " << message << number).






              share|improve this answer

























              • This presumes you don't want to use the << operator for formatting (e.g. cerr << "This log message has been printed " << ntimes << " times." << endl;)

                – Ken Bloom
                Dec 15 '10 at 14:54






              • 2





                Hrm. I'm actually wrong about that, because I forgot temporarily how macros work. All you'd need to do to get formatting is call lerr("This log message has been printed " << ntimes << " times.") and the text substitution would get it right.

                – Ken Bloom
                Dec 15 '10 at 18:53
















              2














              This:



              #define myerr(e) CiriticalSectionLocker crit; std::cerr << e << std::endl;


              works on most compilers for the common case of myerr("ERR: " << message << number).






              share|improve this answer

























              • This presumes you don't want to use the << operator for formatting (e.g. cerr << "This log message has been printed " << ntimes << " times." << endl;)

                – Ken Bloom
                Dec 15 '10 at 14:54






              • 2





                Hrm. I'm actually wrong about that, because I forgot temporarily how macros work. All you'd need to do to get formatting is call lerr("This log message has been printed " << ntimes << " times.") and the text substitution would get it right.

                – Ken Bloom
                Dec 15 '10 at 18:53














              2












              2








              2







              This:



              #define myerr(e) CiriticalSectionLocker crit; std::cerr << e << std::endl;


              works on most compilers for the common case of myerr("ERR: " << message << number).






              share|improve this answer















              This:



              #define myerr(e) CiriticalSectionLocker crit; std::cerr << e << std::endl;


              works on most compilers for the common case of myerr("ERR: " << message << number).







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Dec 18 '10 at 1:47

























              answered Dec 15 '10 at 5:01









              unixman83unixman83

              4,66895391




              4,66895391












              • This presumes you don't want to use the << operator for formatting (e.g. cerr << "This log message has been printed " << ntimes << " times." << endl;)

                – Ken Bloom
                Dec 15 '10 at 14:54






              • 2





                Hrm. I'm actually wrong about that, because I forgot temporarily how macros work. All you'd need to do to get formatting is call lerr("This log message has been printed " << ntimes << " times.") and the text substitution would get it right.

                – Ken Bloom
                Dec 15 '10 at 18:53


















              • This presumes you don't want to use the << operator for formatting (e.g. cerr << "This log message has been printed " << ntimes << " times." << endl;)

                – Ken Bloom
                Dec 15 '10 at 14:54






              • 2





                Hrm. I'm actually wrong about that, because I forgot temporarily how macros work. All you'd need to do to get formatting is call lerr("This log message has been printed " << ntimes << " times.") and the text substitution would get it right.

                – Ken Bloom
                Dec 15 '10 at 18:53

















              This presumes you don't want to use the << operator for formatting (e.g. cerr << "This log message has been printed " << ntimes << " times." << endl;)

              – Ken Bloom
              Dec 15 '10 at 14:54





              This presumes you don't want to use the << operator for formatting (e.g. cerr << "This log message has been printed " << ntimes << " times." << endl;)

              – Ken Bloom
              Dec 15 '10 at 14:54




              2




              2





              Hrm. I'm actually wrong about that, because I forgot temporarily how macros work. All you'd need to do to get formatting is call lerr("This log message has been printed " << ntimes << " times.") and the text substitution would get it right.

              – Ken Bloom
              Dec 15 '10 at 18:53






              Hrm. I'm actually wrong about that, because I forgot temporarily how macros work. All you'd need to do to get formatting is call lerr("This log message has been printed " << ntimes << " times.") and the text substitution would get it right.

              – Ken Bloom
              Dec 15 '10 at 18:53












              2














              Why not just create a locking class and use it where ever you want to do thread-safe IO?



              class LockIO

              static pthread_mutex_t *mutex;
              public:
              LockIO() pthread_mutex_lock( mutex );
              ~LockIO() pthread_mutex_unlock( mutex );
              ;

              static pthread_mutex_t* getMutex()

              pthread_mutex_t *mutex = new pthread_mutex_t;
              pthread_mutex_init( mutex, NULL );
              return mutex;

              pthread_mutex_t* LockIO::mutex = getMutex();


              Then you put any IO you want in a block:



              std::cout <<"X is " <<x <<std::endl;


              becomes:




              LockIO lock;
              std::cout <<"X is " <<x <<std::endl;






              share|improve this answer





























                2














                Why not just create a locking class and use it where ever you want to do thread-safe IO?



                class LockIO

                static pthread_mutex_t *mutex;
                public:
                LockIO() pthread_mutex_lock( mutex );
                ~LockIO() pthread_mutex_unlock( mutex );
                ;

                static pthread_mutex_t* getMutex()

                pthread_mutex_t *mutex = new pthread_mutex_t;
                pthread_mutex_init( mutex, NULL );
                return mutex;

                pthread_mutex_t* LockIO::mutex = getMutex();


                Then you put any IO you want in a block:



                std::cout <<"X is " <<x <<std::endl;


                becomes:




                LockIO lock;
                std::cout <<"X is " <<x <<std::endl;






                share|improve this answer



























                  2












                  2








                  2







                  Why not just create a locking class and use it where ever you want to do thread-safe IO?



                  class LockIO

                  static pthread_mutex_t *mutex;
                  public:
                  LockIO() pthread_mutex_lock( mutex );
                  ~LockIO() pthread_mutex_unlock( mutex );
                  ;

                  static pthread_mutex_t* getMutex()

                  pthread_mutex_t *mutex = new pthread_mutex_t;
                  pthread_mutex_init( mutex, NULL );
                  return mutex;

                  pthread_mutex_t* LockIO::mutex = getMutex();


                  Then you put any IO you want in a block:



                  std::cout <<"X is " <<x <<std::endl;


                  becomes:




                  LockIO lock;
                  std::cout <<"X is " <<x <<std::endl;






                  share|improve this answer















                  Why not just create a locking class and use it where ever you want to do thread-safe IO?



                  class LockIO

                  static pthread_mutex_t *mutex;
                  public:
                  LockIO() pthread_mutex_lock( mutex );
                  ~LockIO() pthread_mutex_unlock( mutex );
                  ;

                  static pthread_mutex_t* getMutex()

                  pthread_mutex_t *mutex = new pthread_mutex_t;
                  pthread_mutex_init( mutex, NULL );
                  return mutex;

                  pthread_mutex_t* LockIO::mutex = getMutex();


                  Then you put any IO you want in a block:



                  std::cout <<"X is " <<x <<std::endl;


                  becomes:




                  LockIO lock;
                  std::cout <<"X is " <<x <<std::endl;







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Mar 6 '13 at 0:37









                  andr

                  14k103854




                  14k103854










                  answered Mar 6 '13 at 0:19









                  Daniel WisehartDaniel Wisehart

                  1,3971029




                  1,3971029





















                      2














                      If available, osyncstream (C++20) solves this problem:



                      #include <syncstream> // C++20

                      std::osyncstream tout(std::cout);
                      std::osyncstream terr(std::cerr);



                      If the above feature is not available, here is a drop-in header file containing two macros for thread-safe writing to std::cout and std::cerr (which must share a mutex in order to avoid interleaving of output). These are based on two other answers, but I have made some changes to make it easy to drop into an existing code base. This works with C++11 and forward.



                      I've tested this with 4 threads on a 4-core processor, with each thread writing 25,000 lines per second to tout and occasional output to terr, and it solves the output interleaving problem. Unlike a struct-based solution, there was no measurable performance hit for my application when dropping in this header file. The only drawback I can think of is that since this relies on macros, they can't be placed into a namespace.



                      threadstream.h



                      #ifndef THREADSTREAM
                      #define THREADSTREAM

                      #include <iostream>
                      #include <sstream>
                      #include <mutex>

                      #define terr ThreadStream(std::cerr)
                      #define tout ThreadStream(std::cout)

                      /**
                      * Thread-safe std::ostream class.
                      *
                      * Usage:
                      * tout << "Hello world!" << std::endl;
                      * terr << "Hello world!" << std::endl;
                      */
                      class ThreadStream : public std::ostringstream

                      public:
                      ThreadStream(std::ostream& os) : os_(os)

                      // copyfmt causes odd problems with lost output
                      // probably some specific flag
                      // copyfmt(os);
                      // copy whatever properties are relevant
                      imbue(os.getloc());
                      precision(os.precision());
                      width(os.width());
                      setf(std::ios::fixed, std::ios::floatfield);


                      ~ThreadStream()

                      std::lock_guard<std::mutex> guard(_mutex_threadstream);
                      os_ << this->str();


                      private:
                      static std::mutex _mutex_threadstream;
                      std::ostream& os_;
                      ;

                      std::mutex ThreadStream::_mutex_threadstream;

                      #endif



                      test.cc



                      #include <thread>
                      #include <vector>
                      #include <iomanip>
                      #include "threadstream.h"

                      void test(const unsigned int threadNumber)

                      tout << "Thread " << threadNumber << ": launched" << std::endl;


                      int main()

                      std::locale mylocale(""); // get global locale
                      std::cerr.imbue(mylocale); // imbue global locale
                      std::ios_base::sync_with_stdio(false); // disable synch with stdio (enables input buffering)

                      std::cout << std::fixed << std::setw(4) << std::setprecision(5);
                      std::cerr << std::fixed << std::setw(2) << std::setprecision(2);

                      std::vector<std::thread> threads;

                      for (unsigned int threadNumber = 0; threadNumber < 16; threadNumber++)

                      std::thread t(test, threadNumber);
                      threads.push_back(std::move(t));


                      for (std::thread& t : threads)

                      if (t.joinable())

                      t.join();



                      terr << std::endl << "Main: " << "Test completed." << std::endl;

                      return 0;




                      compiling



                      g++ -g -O2 -Wall -c -o test.o test.cc
                      g++ -o test test.o -pthread



                      output



                      ./test
                      Thread 0: launched
                      Thread 4: launched
                      Thread 3: launched
                      Thread 1: launched
                      Thread 2: launched
                      Thread 6: launched
                      Thread 5: launched
                      Thread 7: launched
                      Thread 8: launched
                      Thread 9: launched
                      Thread 10: launched
                      Thread 11: launched
                      Thread 12: launched
                      Thread 13: launched
                      Thread 14: launched
                      Thread 15: launched

                      Main: Test completed.





                      share|improve this answer

























                      • Awesome, thanks!

                        – thc
                        Mar 12 at 18:41















                      2














                      If available, osyncstream (C++20) solves this problem:



                      #include <syncstream> // C++20

                      std::osyncstream tout(std::cout);
                      std::osyncstream terr(std::cerr);



                      If the above feature is not available, here is a drop-in header file containing two macros for thread-safe writing to std::cout and std::cerr (which must share a mutex in order to avoid interleaving of output). These are based on two other answers, but I have made some changes to make it easy to drop into an existing code base. This works with C++11 and forward.



                      I've tested this with 4 threads on a 4-core processor, with each thread writing 25,000 lines per second to tout and occasional output to terr, and it solves the output interleaving problem. Unlike a struct-based solution, there was no measurable performance hit for my application when dropping in this header file. The only drawback I can think of is that since this relies on macros, they can't be placed into a namespace.



                      threadstream.h



                      #ifndef THREADSTREAM
                      #define THREADSTREAM

                      #include <iostream>
                      #include <sstream>
                      #include <mutex>

                      #define terr ThreadStream(std::cerr)
                      #define tout ThreadStream(std::cout)

                      /**
                      * Thread-safe std::ostream class.
                      *
                      * Usage:
                      * tout << "Hello world!" << std::endl;
                      * terr << "Hello world!" << std::endl;
                      */
                      class ThreadStream : public std::ostringstream

                      public:
                      ThreadStream(std::ostream& os) : os_(os)

                      // copyfmt causes odd problems with lost output
                      // probably some specific flag
                      // copyfmt(os);
                      // copy whatever properties are relevant
                      imbue(os.getloc());
                      precision(os.precision());
                      width(os.width());
                      setf(std::ios::fixed, std::ios::floatfield);


                      ~ThreadStream()

                      std::lock_guard<std::mutex> guard(_mutex_threadstream);
                      os_ << this->str();


                      private:
                      static std::mutex _mutex_threadstream;
                      std::ostream& os_;
                      ;

                      std::mutex ThreadStream::_mutex_threadstream;

                      #endif



                      test.cc



                      #include <thread>
                      #include <vector>
                      #include <iomanip>
                      #include "threadstream.h"

                      void test(const unsigned int threadNumber)

                      tout << "Thread " << threadNumber << ": launched" << std::endl;


                      int main()

                      std::locale mylocale(""); // get global locale
                      std::cerr.imbue(mylocale); // imbue global locale
                      std::ios_base::sync_with_stdio(false); // disable synch with stdio (enables input buffering)

                      std::cout << std::fixed << std::setw(4) << std::setprecision(5);
                      std::cerr << std::fixed << std::setw(2) << std::setprecision(2);

                      std::vector<std::thread> threads;

                      for (unsigned int threadNumber = 0; threadNumber < 16; threadNumber++)

                      std::thread t(test, threadNumber);
                      threads.push_back(std::move(t));


                      for (std::thread& t : threads)

                      if (t.joinable())

                      t.join();



                      terr << std::endl << "Main: " << "Test completed." << std::endl;

                      return 0;




                      compiling



                      g++ -g -O2 -Wall -c -o test.o test.cc
                      g++ -o test test.o -pthread



                      output



                      ./test
                      Thread 0: launched
                      Thread 4: launched
                      Thread 3: launched
                      Thread 1: launched
                      Thread 2: launched
                      Thread 6: launched
                      Thread 5: launched
                      Thread 7: launched
                      Thread 8: launched
                      Thread 9: launched
                      Thread 10: launched
                      Thread 11: launched
                      Thread 12: launched
                      Thread 13: launched
                      Thread 14: launched
                      Thread 15: launched

                      Main: Test completed.





                      share|improve this answer

























                      • Awesome, thanks!

                        – thc
                        Mar 12 at 18:41













                      2












                      2








                      2







                      If available, osyncstream (C++20) solves this problem:



                      #include <syncstream> // C++20

                      std::osyncstream tout(std::cout);
                      std::osyncstream terr(std::cerr);



                      If the above feature is not available, here is a drop-in header file containing two macros for thread-safe writing to std::cout and std::cerr (which must share a mutex in order to avoid interleaving of output). These are based on two other answers, but I have made some changes to make it easy to drop into an existing code base. This works with C++11 and forward.



                      I've tested this with 4 threads on a 4-core processor, with each thread writing 25,000 lines per second to tout and occasional output to terr, and it solves the output interleaving problem. Unlike a struct-based solution, there was no measurable performance hit for my application when dropping in this header file. The only drawback I can think of is that since this relies on macros, they can't be placed into a namespace.



                      threadstream.h



                      #ifndef THREADSTREAM
                      #define THREADSTREAM

                      #include <iostream>
                      #include <sstream>
                      #include <mutex>

                      #define terr ThreadStream(std::cerr)
                      #define tout ThreadStream(std::cout)

                      /**
                      * Thread-safe std::ostream class.
                      *
                      * Usage:
                      * tout << "Hello world!" << std::endl;
                      * terr << "Hello world!" << std::endl;
                      */
                      class ThreadStream : public std::ostringstream

                      public:
                      ThreadStream(std::ostream& os) : os_(os)

                      // copyfmt causes odd problems with lost output
                      // probably some specific flag
                      // copyfmt(os);
                      // copy whatever properties are relevant
                      imbue(os.getloc());
                      precision(os.precision());
                      width(os.width());
                      setf(std::ios::fixed, std::ios::floatfield);


                      ~ThreadStream()

                      std::lock_guard<std::mutex> guard(_mutex_threadstream);
                      os_ << this->str();


                      private:
                      static std::mutex _mutex_threadstream;
                      std::ostream& os_;
                      ;

                      std::mutex ThreadStream::_mutex_threadstream;

                      #endif



                      test.cc



                      #include <thread>
                      #include <vector>
                      #include <iomanip>
                      #include "threadstream.h"

                      void test(const unsigned int threadNumber)

                      tout << "Thread " << threadNumber << ": launched" << std::endl;


                      int main()

                      std::locale mylocale(""); // get global locale
                      std::cerr.imbue(mylocale); // imbue global locale
                      std::ios_base::sync_with_stdio(false); // disable synch with stdio (enables input buffering)

                      std::cout << std::fixed << std::setw(4) << std::setprecision(5);
                      std::cerr << std::fixed << std::setw(2) << std::setprecision(2);

                      std::vector<std::thread> threads;

                      for (unsigned int threadNumber = 0; threadNumber < 16; threadNumber++)

                      std::thread t(test, threadNumber);
                      threads.push_back(std::move(t));


                      for (std::thread& t : threads)

                      if (t.joinable())

                      t.join();



                      terr << std::endl << "Main: " << "Test completed." << std::endl;

                      return 0;




                      compiling



                      g++ -g -O2 -Wall -c -o test.o test.cc
                      g++ -o test test.o -pthread



                      output



                      ./test
                      Thread 0: launched
                      Thread 4: launched
                      Thread 3: launched
                      Thread 1: launched
                      Thread 2: launched
                      Thread 6: launched
                      Thread 5: launched
                      Thread 7: launched
                      Thread 8: launched
                      Thread 9: launched
                      Thread 10: launched
                      Thread 11: launched
                      Thread 12: launched
                      Thread 13: launched
                      Thread 14: launched
                      Thread 15: launched

                      Main: Test completed.





                      share|improve this answer















                      If available, osyncstream (C++20) solves this problem:



                      #include <syncstream> // C++20

                      std::osyncstream tout(std::cout);
                      std::osyncstream terr(std::cerr);



                      If the above feature is not available, here is a drop-in header file containing two macros for thread-safe writing to std::cout and std::cerr (which must share a mutex in order to avoid interleaving of output). These are based on two other answers, but I have made some changes to make it easy to drop into an existing code base. This works with C++11 and forward.



                      I've tested this with 4 threads on a 4-core processor, with each thread writing 25,000 lines per second to tout and occasional output to terr, and it solves the output interleaving problem. Unlike a struct-based solution, there was no measurable performance hit for my application when dropping in this header file. The only drawback I can think of is that since this relies on macros, they can't be placed into a namespace.



                      threadstream.h



                      #ifndef THREADSTREAM
                      #define THREADSTREAM

                      #include <iostream>
                      #include <sstream>
                      #include <mutex>

                      #define terr ThreadStream(std::cerr)
                      #define tout ThreadStream(std::cout)

                      /**
                      * Thread-safe std::ostream class.
                      *
                      * Usage:
                      * tout << "Hello world!" << std::endl;
                      * terr << "Hello world!" << std::endl;
                      */
                      class ThreadStream : public std::ostringstream

                      public:
                      ThreadStream(std::ostream& os) : os_(os)

                      // copyfmt causes odd problems with lost output
                      // probably some specific flag
                      // copyfmt(os);
                      // copy whatever properties are relevant
                      imbue(os.getloc());
                      precision(os.precision());
                      width(os.width());
                      setf(std::ios::fixed, std::ios::floatfield);


                      ~ThreadStream()

                      std::lock_guard<std::mutex> guard(_mutex_threadstream);
                      os_ << this->str();


                      private:
                      static std::mutex _mutex_threadstream;
                      std::ostream& os_;
                      ;

                      std::mutex ThreadStream::_mutex_threadstream;

                      #endif



                      test.cc



                      #include <thread>
                      #include <vector>
                      #include <iomanip>
                      #include "threadstream.h"

                      void test(const unsigned int threadNumber)

                      tout << "Thread " << threadNumber << ": launched" << std::endl;


                      int main()

                      std::locale mylocale(""); // get global locale
                      std::cerr.imbue(mylocale); // imbue global locale
                      std::ios_base::sync_with_stdio(false); // disable synch with stdio (enables input buffering)

                      std::cout << std::fixed << std::setw(4) << std::setprecision(5);
                      std::cerr << std::fixed << std::setw(2) << std::setprecision(2);

                      std::vector<std::thread> threads;

                      for (unsigned int threadNumber = 0; threadNumber < 16; threadNumber++)

                      std::thread t(test, threadNumber);
                      threads.push_back(std::move(t));


                      for (std::thread& t : threads)

                      if (t.joinable())

                      t.join();



                      terr << std::endl << "Main: " << "Test completed." << std::endl;

                      return 0;




                      compiling



                      g++ -g -O2 -Wall -c -o test.o test.cc
                      g++ -o test test.o -pthread



                      output



                      ./test
                      Thread 0: launched
                      Thread 4: launched
                      Thread 3: launched
                      Thread 1: launched
                      Thread 2: launched
                      Thread 6: launched
                      Thread 5: launched
                      Thread 7: launched
                      Thread 8: launched
                      Thread 9: launched
                      Thread 10: launched
                      Thread 11: launched
                      Thread 12: launched
                      Thread 13: launched
                      Thread 14: launched
                      Thread 15: launched

                      Main: Test completed.






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Nov 14 '18 at 17:23

























                      answered Nov 13 '18 at 19:22









                      vallismortisvallismortis

                      3,684104366




                      3,684104366












                      • Awesome, thanks!

                        – thc
                        Mar 12 at 18:41

















                      • Awesome, thanks!

                        – thc
                        Mar 12 at 18:41
















                      Awesome, thanks!

                      – thc
                      Mar 12 at 18:41





                      Awesome, thanks!

                      – thc
                      Mar 12 at 18:41











                      1














                      An improvement (that doesn't really fit in a comment) on the approach in unixman's comment.



                      #define LOCKED_ERR 
                      if(ErrCriticalSectionLocker crit = ErrCriticalSectionLocker());
                      else std::cerr


                      Which can be used like



                      LOCKED_ERR << "ERR: " << message << endl;


                      if ErrCriticalSectionLocker is implemented carefully.



                      But, I would personally prefer Ken's suggestion.






                      share|improve this answer























                      • +1 for creative use of the lifecycle of temporaries. Could you provide an implementation of ErrCriticalSectionLocker, becuase the semantics are very non-trivial?

                        – Ken Bloom
                        Dec 15 '10 at 14:55












                      • Hmm. I see; You can use this method without parenthesis but I see little point in that, since my C (I come from C background) programming style generally calls for parenthesis. Also, ErrCriticalSectionLocker is confusing...

                        – unixman83
                        Jul 18 '11 at 9:00
















                      1














                      An improvement (that doesn't really fit in a comment) on the approach in unixman's comment.



                      #define LOCKED_ERR 
                      if(ErrCriticalSectionLocker crit = ErrCriticalSectionLocker());
                      else std::cerr


                      Which can be used like



                      LOCKED_ERR << "ERR: " << message << endl;


                      if ErrCriticalSectionLocker is implemented carefully.



                      But, I would personally prefer Ken's suggestion.






                      share|improve this answer























                      • +1 for creative use of the lifecycle of temporaries. Could you provide an implementation of ErrCriticalSectionLocker, becuase the semantics are very non-trivial?

                        – Ken Bloom
                        Dec 15 '10 at 14:55












                      • Hmm. I see; You can use this method without parenthesis but I see little point in that, since my C (I come from C background) programming style generally calls for parenthesis. Also, ErrCriticalSectionLocker is confusing...

                        – unixman83
                        Jul 18 '11 at 9:00














                      1












                      1








                      1







                      An improvement (that doesn't really fit in a comment) on the approach in unixman's comment.



                      #define LOCKED_ERR 
                      if(ErrCriticalSectionLocker crit = ErrCriticalSectionLocker());
                      else std::cerr


                      Which can be used like



                      LOCKED_ERR << "ERR: " << message << endl;


                      if ErrCriticalSectionLocker is implemented carefully.



                      But, I would personally prefer Ken's suggestion.






                      share|improve this answer













                      An improvement (that doesn't really fit in a comment) on the approach in unixman's comment.



                      #define LOCKED_ERR 
                      if(ErrCriticalSectionLocker crit = ErrCriticalSectionLocker());
                      else std::cerr


                      Which can be used like



                      LOCKED_ERR << "ERR: " << message << endl;


                      if ErrCriticalSectionLocker is implemented carefully.



                      But, I would personally prefer Ken's suggestion.







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Dec 15 '10 at 6:45









                      Chris HopmanChris Hopman

                      1,9021010




                      1,9021010












                      • +1 for creative use of the lifecycle of temporaries. Could you provide an implementation of ErrCriticalSectionLocker, becuase the semantics are very non-trivial?

                        – Ken Bloom
                        Dec 15 '10 at 14:55












                      • Hmm. I see; You can use this method without parenthesis but I see little point in that, since my C (I come from C background) programming style generally calls for parenthesis. Also, ErrCriticalSectionLocker is confusing...

                        – unixman83
                        Jul 18 '11 at 9:00


















                      • +1 for creative use of the lifecycle of temporaries. Could you provide an implementation of ErrCriticalSectionLocker, becuase the semantics are very non-trivial?

                        – Ken Bloom
                        Dec 15 '10 at 14:55












                      • Hmm. I see; You can use this method without parenthesis but I see little point in that, since my C (I come from C background) programming style generally calls for parenthesis. Also, ErrCriticalSectionLocker is confusing...

                        – unixman83
                        Jul 18 '11 at 9:00

















                      +1 for creative use of the lifecycle of temporaries. Could you provide an implementation of ErrCriticalSectionLocker, becuase the semantics are very non-trivial?

                      – Ken Bloom
                      Dec 15 '10 at 14:55






                      +1 for creative use of the lifecycle of temporaries. Could you provide an implementation of ErrCriticalSectionLocker, becuase the semantics are very non-trivial?

                      – Ken Bloom
                      Dec 15 '10 at 14:55














                      Hmm. I see; You can use this method without parenthesis but I see little point in that, since my C (I come from C background) programming style generally calls for parenthesis. Also, ErrCriticalSectionLocker is confusing...

                      – unixman83
                      Jul 18 '11 at 9:00






                      Hmm. I see; You can use this method without parenthesis but I see little point in that, since my C (I come from C background) programming style generally calls for parenthesis. Also, ErrCriticalSectionLocker is confusing...

                      – unixman83
                      Jul 18 '11 at 9:00


















                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f4446484%2fa-line-based-thread-safe-stdcerr-for-c%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

                      Edmonton

                      Crossroads (UK TV series)