Program Listing for File Clock.cpp
↰ Return to documentation for file (src/Clock.cpp
)
#include "crpropa/Clock.h"
#if defined(WIN32) || defined(_WIN32)
#define USE_WINDOWS_TIMERS
#define WIN32_LEAN_AND_MEAN
#define NOWINRES
#define NOMCX
#define NOIME
#ifdef _XBOX
#include <Xtl.h>
#else
#include <windows.h>
#endif
#include <ctime>
#else
#include <sys/time.h>
#endif
#include <algorithm>
#ifdef _OPENMP
#include <omp.h>
#include <stdexcept>
#endif
namespace crpropa {
#ifdef WIN32
class Clock::Impl {
LARGE_INTEGER clockFrequency;
DWORD startTick;
LONGLONG prevElapsedTime;
LARGE_INTEGER startTime;
public:
Impl() {
QueryPerformanceFrequency(&clockFrequency);
reset();
}
void reset() {
QueryPerformanceCounter(&startTime);
startTick = GetTickCount();
prevElapsedTime = 0;
}
double getSecond() {
LARGE_INTEGER currentTime;
QueryPerformanceCounter(¤tTime);
LONGLONG elapsedTime = currentTime.QuadPart - startTime.QuadPart;
// Compute the number of millisecond ticks elapsed.
unsigned long msecTicks = (unsigned long) (1000 * elapsedTime
/ clockFrequency.QuadPart);
// Check for unexpected leaps in the Win32 performance counter.
// (This is caused by unexpected data across the PCI to ISA
// bridge, aka south bridge. See Microsoft KB274323.)
unsigned long elapsedTicks = GetTickCount() - startTick;
signed long msecOff = (signed long) (msecTicks - elapsedTicks);
if (msecOff < -100 || msecOff > 100) {
// Adjust the starting time forwards.
LONGLONG msecAdjustment = std::min(
msecOff * clockFrequency.QuadPart / 1000,
elapsedTime - prevElapsedTime);
startTime.QuadPart += msecAdjustment;
elapsedTime -= msecAdjustment;
}
// Store the current elapsed time for adjustments next time.
prevElapsedTime = elapsedTime;
// Convert to microseconds.
unsigned long usecTicks = (unsigned long) (1000000 * elapsedTime
/ clockFrequency.QuadPart);
return double(usecTicks) / 1000000;
}
};
#else
class Clock::Impl {
struct timeval startTime;
public:
Impl() {
reset();
}
void reset() {
gettimeofday(&startTime, 0);
}
double getTime() {
struct timeval currentTime;
gettimeofday(¤tTime, 0);
double t = double(currentTime.tv_sec - startTime.tv_sec);
t += double(currentTime.tv_usec - startTime.tv_usec) / 1000000.;
return t;
}
};
#endif
Clock::Clock() {
impl = new Impl;
}
Clock::~Clock() {
delete impl;
}
void Clock::reset() {
impl->reset();
}
double Clock::getSecond() {
return impl->getTime();
}
double Clock::getMillisecond() {
return impl->getTime() * 1000;
}
#ifdef _OPENMP
// see http://stackoverflow.com/questions/8051108/using-the-openmp-threadprivate-directive-on-static-instances-of-c-stl-types
const static int MAX_THREAD = 256;
struct CLOCK_TLS_ITEM {
Clock r;
char padding[(sizeof(Clock) / 64 + 1) * 64 - sizeof(Clock)];
};
Clock &Clock::getInstance() {
#ifdef _MSC_VER
__declspec(align(64)) static CLOCK_TLS_ITEM tls[MAX_THREAD];
#else
__attribute__ ((aligned(64))) static CLOCK_TLS_ITEM tls[MAX_THREAD];
#endif
int i = omp_get_thread_num();
if (i >= MAX_THREAD)
throw std::runtime_error("crpropa::Clock: more than MAX_THREAD threads!");
return tls[i].r;
}
#else
Clock &Clock::getInstance() {
static Clock r;
return r;
}
#endif
} /* namespace scs */