Voici une solution de journalisation basée sur les threads sûrs que j'ai cuits à un moment donné. Il utilise boost mutex pour la sécurité des threads. Il est un peu plus compliqué que nécessaire parce que vous pouvez brancher dans les politiques de sortie (si il aller à un fichier, stderr, ou ailleurs?):
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
Utilisation ressemble à ceci:
logger::log() << "this is a test" << 1234 << "testing";
note l'absence d'un '\n'
et std::endl
puisqu'il est implicite. Les contenus sont mis en mémoire tampon puis sortis de façon atomique à l'aide de la stratégie spécifiée par le modèle. Cette implémentation ajoute également un horodatage à la ligne, car elle sert à la consignation. La politique no_output
est strictement facultative, c'est ce que j'utilise lorsque je veux désactiver la journalisation.
Comment imaginez-vous la création d'un tampon local de fil "accroché" dans 'std :: cerr' réduirait la mise en mémoire tampon sur un tampon local de thread "outside", puis écrirait des lignes entières dans 'std :: cerr'? Un tampon est un tampon. 'std :: ostringstream' est une approche typique à usage général pour cela. –
Êtes-vous par hasard à la recherche d'une bibliothèque de journalisation thread-safe? – yasouser
J'ai récemment pris connaissance du projet log4cpp (http://log4cpp.sourceforge.net/). Vous ne savez pas si c'est ce que vous cherchez!?!? Peut-être utile de vérifier. – yasouser