<tb@panthema.net>
<http://www.gnu.org/licenses/>
#ifndef TOOLS_AGGLOGGER_H
#define TOOLS_AGGLOGGER_H
#include <fstream>
#include <iomanip>
#include <limits>
#include <omp.h>
template <typename ValueType>
class AggregateLogger
{
public:
typedef ValueType value_type;
protected:
static inline double timestamp()
{
return omp_get_wtime();
}
protected:
template <typename AggFunctor>
class TemplateLogger
{
protected:
std::ofstream m_logfile;
double m_begintime;
double m_endtime;
double m_zerotime;
size_t m_count;
value_type m_aggregate;
double m_max_interval;
size_t m_max_count;
inline void output()
{
m_logfile << std::setprecision(16)
<< ((m_begintime + m_endtime) / 2.0) - m_zerotime << " "
<< AggFunctor::output(m_aggregate, m_count) << " "
<< m_count << std::endl;
}
public:
TemplateLogger(const char* logname, double max_interval = 0.01,
size_t max_count = 1000, bool append = false)
: m_logfile(logname, append ? std::ios::app : std::ios::out),
m_begintime(0),
m_zerotime(timestamp()),
m_max_interval(max_interval),
m_max_count(max_count)
{
}
TemplateLogger& start()
{
m_zerotime = timestamp();
return *this;
}
TemplateLogger& operator << (const value_type& value)
{
double thistime = timestamp();
if (m_begintime == 0)
{
m_begintime = m_endtime = thistime;
m_count = 1;
m_aggregate = AggFunctor::aggregate(AggFunctor::initial(), value);
}
else if (thistime - m_begintime > m_max_interval ||
m_count >= m_max_count)
{
output();
m_begintime = m_endtime = thistime;
m_count = 1;
m_aggregate = AggFunctor::aggregate(AggFunctor::initial(), value);
}
else
{
m_endtime = thistime;
m_count++;
m_aggregate = AggFunctor::aggregate(m_aggregate, value);
}
return *this;
}
~TemplateLogger()
{
if (m_begintime != 0)
output();
}
};
struct MaxLoggerFunctor
{
static inline value_type initial()
{
return std::numeric_limits<value_type>::min();
}
static inline value_type aggregate(const value_type& prev, const value_type& sample)
{
return std::max(prev, sample);
}
static inline const value_type& output(const value_type& aggregate, size_t )
{
return aggregate;
}
};
struct MinLoggerFunctor
{
static inline value_type initial()
{
return std::numeric_limits<value_type>::max();
}
static inline value_type aggregate(const value_type& prev, const value_type& sample)
{
return std::min(prev, sample);
}
static inline const value_type& output(const value_type& aggregate, size_t )
{
return aggregate;
}
};
struct AvgLoggerFunctor
{
static inline value_type initial()
{
return 0;
}
static inline value_type aggregate(const value_type& prev, const value_type& sample)
{
return prev + sample;
}
static inline double output(const value_type& aggregate, size_t count)
{
return aggregate / (double)count;
}
};
public:
typedef TemplateLogger<MaxLoggerFunctor> MaximumLogger;
typedef TemplateLogger<MaxLoggerFunctor> MaxLogger;
typedef TemplateLogger<MinLoggerFunctor> MinimumLogger;
typedef TemplateLogger<MinLoggerFunctor> MinLogger;
typedef TemplateLogger<AvgLoggerFunctor> AverageLogger;
typedef TemplateLogger<AvgLoggerFunctor> AvgLogger;
protected:
template <typename BaseLogger>
class LockingLogger : protected BaseLogger
{
public:
LockingLogger(const char* logname, double max_interval = 0.01,
size_t max_count = 1000, bool append = false)
: BaseLogger(logname, max_interval, max_count, append)
{
}
LockingLogger& start()
{
BaseLogger::start();
return *this;
}
LockingLogger& operator << (const value_type& value)
{
#pragma omp critical
BaseLogger::operator << (value);
return *this;
}
};
public:
typedef LockingLogger<MinLogger> LockingMinLogger;
typedef LockingLogger<MinLogger> LockingMinimumLogger;
typedef LockingLogger<MaxLogger> LockingMaxLogger;
typedef LockingLogger<MaxLogger> LockingMaximumLogger;
typedef LockingLogger<AvgLogger> LockingAvgLogger;
typedef LockingLogger<AvgLogger> LockingAverageLogger;
protected:
class DummyLogger
{
public:
DummyLogger(const char* , double = 0,
double = 0, bool = false)
{ }
DummyLogger& start()
{
return *this;
}
DummyLogger& operator<< (const value_type& )
{
return *this;
}
};
};
#endif