Line data Source code
1 : #include "crpropa/Clock.h" 2 : 3 : #if defined(WIN32) || defined(_WIN32) 4 : 5 : #define USE_WINDOWS_TIMERS 6 : #define WIN32_LEAN_AND_MEAN 7 : #define NOWINRES 8 : #define NOMCX 9 : #define NOIME 10 : #ifdef _XBOX 11 : #include <Xtl.h> 12 : #else 13 : #include <windows.h> 14 : #endif 15 : #include <ctime> 16 : 17 : #else 18 : #include <sys/time.h> 19 : #endif 20 : 21 : #include <algorithm> 22 : #ifdef _OPENMP 23 : #include <omp.h> 24 : #include <stdexcept> 25 : #endif 26 : 27 : namespace crpropa { 28 : 29 : #ifdef WIN32 30 : class Clock::Impl { 31 : LARGE_INTEGER clockFrequency; 32 : DWORD startTick; 33 : LONGLONG prevElapsedTime; 34 : LARGE_INTEGER startTime; 35 : public: 36 : Impl() { 37 : QueryPerformanceFrequency(&clockFrequency); 38 : reset(); 39 : } 40 : 41 : void reset() { 42 : QueryPerformanceCounter(&startTime); 43 : startTick = GetTickCount(); 44 : prevElapsedTime = 0; 45 : } 46 : 47 : /// Returns the time in ms since the last call to reset or since 48 : /// the btClock was created. 49 : double getSecond() { 50 : LARGE_INTEGER currentTime; 51 : QueryPerformanceCounter(¤tTime); 52 : LONGLONG elapsedTime = currentTime.QuadPart - startTime.QuadPart; 53 : 54 : // Compute the number of millisecond ticks elapsed. 55 : unsigned long msecTicks = (unsigned long) (1000 * elapsedTime 56 : / clockFrequency.QuadPart); 57 : 58 : // Check for unexpected leaps in the Win32 performance counter. 59 : // (This is caused by unexpected data across the PCI to ISA 60 : // bridge, aka south bridge. See Microsoft KB274323.) 61 : unsigned long elapsedTicks = GetTickCount() - startTick; 62 : signed long msecOff = (signed long) (msecTicks - elapsedTicks); 63 : if (msecOff < -100 || msecOff > 100) { 64 : // Adjust the starting time forwards. 65 : LONGLONG msecAdjustment = std::min( 66 : msecOff * clockFrequency.QuadPart / 1000, 67 : elapsedTime - prevElapsedTime); 68 : startTime.QuadPart += msecAdjustment; 69 : elapsedTime -= msecAdjustment; 70 : } 71 : 72 : // Store the current elapsed time for adjustments next time. 73 : prevElapsedTime = elapsedTime; 74 : 75 : // Convert to microseconds. 76 : unsigned long usecTicks = (unsigned long) (1000000 * elapsedTime 77 : / clockFrequency.QuadPart); 78 : 79 : return double(usecTicks) / 1000000; 80 : } 81 : }; 82 : #else 83 : 84 : class Clock::Impl { 85 : struct timeval startTime; 86 : public: 87 0 : Impl() { 88 : reset(); 89 : } 90 : 91 : void reset() { 92 0 : gettimeofday(&startTime, 0); 93 : } 94 : 95 : /// Returns the time in since the last call to reset or since 96 : /// the btClock was created. 97 0 : double getTime() { 98 : struct timeval currentTime; 99 0 : gettimeofday(¤tTime, 0); 100 0 : double t = double(currentTime.tv_sec - startTime.tv_sec); 101 0 : t += double(currentTime.tv_usec - startTime.tv_usec) / 1000000.; 102 0 : return t; 103 : } 104 : }; 105 : #endif 106 : 107 0 : Clock::Clock() { 108 0 : impl = new Impl; 109 0 : } 110 : 111 0 : Clock::~Clock() { 112 0 : delete impl; 113 0 : } 114 : 115 0 : void Clock::reset() { 116 0 : impl->reset(); 117 0 : } 118 : 119 0 : double Clock::getSecond() { 120 0 : return impl->getTime(); 121 : } 122 : 123 0 : double Clock::getMillisecond() { 124 0 : return impl->getTime() * 1000; 125 : } 126 : 127 : #ifdef _OPENMP 128 : 129 : // see http://stackoverflow.com/questions/8051108/using-the-openmp-threadprivate-directive-on-static-instances-of-c-stl-types 130 : const static int MAX_THREAD = 256; 131 : 132 0 : struct CLOCK_TLS_ITEM { 133 : Clock r; 134 : char padding[(sizeof(Clock) / 64 + 1) * 64 - sizeof(Clock)]; 135 : }; 136 : 137 0 : Clock &Clock::getInstance() { 138 : #ifdef _MSC_VER 139 : __declspec(align(64)) static CLOCK_TLS_ITEM tls[MAX_THREAD]; 140 : #else 141 0 : __attribute__ ((aligned(64))) static CLOCK_TLS_ITEM tls[MAX_THREAD]; 142 : #endif 143 0 : int i = omp_get_thread_num(); 144 0 : if (i >= MAX_THREAD) 145 0 : throw std::runtime_error("crpropa::Clock: more than MAX_THREAD threads!"); 146 0 : return tls[i].r; 147 : } 148 : #else 149 : Clock &Clock::getInstance() { 150 : static Clock r; 151 : return r; 152 : } 153 : #endif 154 : 155 : } /* namespace scs */