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 */
|