Вот решение, основанное на потоке, основанное на логике, которое я приготовил в какой-то момент. Он использует повышающий мьютекс для обеспечения безопасности потоков. Это немного сложнее, чем это необходимо, потому что вы можете подключить выходные политики (она должна идти в файл, STDERR, или где-нибудь еще?):
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
Использование выглядит следующим образом:
logger::log() << "this is a test" << 1234 << "testing";
сведению отсутствие '\n'
и std::endl
, так как это подразумевается. Содержимое буферизуется, а затем атомарно выводится с использованием политики, указанной в шаблоне. Эта реализация также добавляет строку с меткой времени, поскольку она предназначена для ведения журнала. Политика no_output
строго необязательна, это то, что я использую, когда хочу отключить ведение журнала.
Как вы представляете себе создание потоков локального буфера "горбатый" в 'станд :: cerr' уменьшит буферизацию поверх локального буфера потока «снаружи», а затем написание полных строк в 'std :: cerr'? Буфер - это буфер. 'std :: ostringstream' - типичный общий подход для этого. –
Вы случайно ищете библиотеку протоколов с потоками? – yasouser
Недавно я узнал о проекте log4cpp (http://log4cpp.sourceforge.net/). Не уверен, обеспечивает ли он то, что вы ищете!?!? Может быть, стоит проверить это. – yasouser