#ifndef LOGGER_H #define LOGGER_H #include #include class Logger { std::ostream* m_stream; pthread_mutex_t m_mutex; public: Logger() : m_stream(&std::clog) { pthread_mutex_init(&m_mutex, 0); } ~Logger() { pthread_mutex_destroy(&m_mutex); } std::ostream& stream() { return *m_stream; } void lock() { pthread_mutex_lock(&m_mutex); } void unlock() { pthread_mutex_unlock(&m_mutex); } }; template class LoggerHelperBase { protected: Helper& m_helper; const T& m_value; bool m_active; public: LoggerHelperBase(Helper& helper, const T& value) : m_helper(helper) , m_value(value) , m_active(true) { } void deactivate() { m_active = false; } }; template class LoggerHelper : public LoggerHelperBase { public: LoggerHelper(Helper& helper, const T& value) : LoggerHelperBase(helper, value) { helper.deactivate(); } ~LoggerHelper() { if (m_active) { Logger& logger = getLogger(); logger.lock(); run(logger.stream()); logger.stream() << std::endl; logger.unlock(); } } void run(std::ostream& stream) { m_helper.run(stream); stream << m_value; } Logger& getLogger() { return m_helper.getLogger(); } }; template class LoggerHelper : public LoggerHelperBase { public: LoggerHelper(Logger& logger, const T& value) : LoggerHelperBase(logger, value) { } ~LoggerHelper() { if (m_active) { Logger& logger = m_helper; logger.lock(); run(logger.stream()); logger.stream() << std::endl; logger.unlock(); } } void run(std::ostream& stream) { stream << m_value; } Logger& getLogger() { return m_helper; } }; template LoggerHelper operator<<(Logger& logger, const T& value) { return LoggerHelper(logger, value); } template LoggerHelper, T2> operator<<(LoggerHelper helper, const T2& value) { return LoggerHelper, T2>(helper, value); } #endif // LOGGER_H