1 | /* $Id: CoinTime.hpp 1372 2011-01-03 23:31:00Z lou $ */ |
2 | // Copyright (C) 2002, International Business Machines |
3 | // Corporation and others. All Rights Reserved. |
4 | // This code is licensed under the terms of the Eclipse Public License (EPL). |
5 | |
6 | #ifndef _CoinTime_hpp |
7 | #define _CoinTime_hpp |
8 | |
9 | // Uncomment the next three lines for thorough memory initialisation. |
10 | // #ifndef ZEROFAULT |
11 | // # define ZEROFAULT |
12 | // #endif |
13 | |
14 | //############################################################################# |
15 | |
16 | #include <ctime> |
17 | #if defined(_MSC_VER) |
18 | // Turn off compiler warning about long names |
19 | # pragma warning(disable:4786) |
20 | #else |
21 | // MacOS-X and FreeBSD needs sys/time.h |
22 | #if defined(__MACH__) || defined (__FreeBSD__) |
23 | #include <sys/time.h> |
24 | #endif |
25 | #if !defined(__MSVCRT__) |
26 | #include <sys/resource.h> |
27 | #endif |
28 | #endif |
29 | |
30 | //############################################################################# |
31 | |
32 | #if defined(_MSC_VER) |
33 | |
34 | #if 0 // change this to 1 if want to use the win32 API |
35 | #include <windows.h> |
36 | #ifdef small |
37 | /* for some unfathomable reason (to me) rpcndr.h (pulled in by windows.h) does a |
38 | '#define small char' */ |
39 | #undef small |
40 | #endif |
41 | #define TWO_TO_THE_THIRTYTWO 4294967296.0 |
42 | #define DELTA_EPOCH_IN_SECS 11644473600.0 |
43 | inline double CoinGetTimeOfDay() |
44 | { |
45 | FILETIME ft; |
46 | |
47 | GetSystemTimeAsFileTime(&ft); |
48 | double t = ft.dwHighDateTime * TWO_TO_THE_THIRTYTWO + ft.dwLowDateTime; |
49 | t = t/10000000.0 - DELTA_EPOCH_IN_SECS; |
50 | return t; |
51 | } |
52 | #else |
53 | #include <sys/types.h> |
54 | #include <sys/timeb.h> |
55 | inline double CoinGetTimeOfDay() |
56 | { |
57 | struct _timeb timebuffer; |
58 | #pragma warning(disable:4996) |
59 | _ftime( &timebuffer ); // C4996 |
60 | #pragma warning(default:4996) |
61 | return timebuffer.time + timebuffer.millitm/1000.0; |
62 | } |
63 | #endif |
64 | |
65 | #else |
66 | |
67 | #include <sys/time.h> |
68 | |
69 | inline double CoinGetTimeOfDay() |
70 | { |
71 | struct timeval tv; |
72 | gettimeofday(&tv, nullptr); |
73 | return static_cast<double>(tv.tv_sec) + static_cast<int>(tv.tv_usec)/1000000.0; |
74 | } |
75 | |
76 | #endif // _MSC_VER |
77 | |
78 | /** |
79 | Query the elapsed wallclock time since the first call to this function. If |
80 | a positive argument is passed to the function then the time of the first |
81 | call is set to that value (this kind of argument is allowed only at the |
82 | first call!). If a negative argument is passed to the function then it |
83 | returns the time when it was set. |
84 | */ |
85 | |
86 | inline double CoinWallclockTime(double callType = 0) |
87 | { |
88 | double callTime = CoinGetTimeOfDay(); |
89 | static const double firstCall = callType > 0 ? callType : callTime; |
90 | return callType < 0 ? firstCall : callTime - firstCall; |
91 | } |
92 | |
93 | //############################################################################# |
94 | |
95 | //#define HAVE_SDK // if SDK under Win32 is installed, for CPU instead of elapsed time under Win |
96 | #ifdef HAVE_SDK |
97 | #include <windows.h> |
98 | #ifdef small |
99 | /* for some unfathomable reason (to me) rpcndr.h (pulled in by windows.h) does a |
100 | '#define small char' */ |
101 | #undef small |
102 | #endif |
103 | #define TWO_TO_THE_THIRTYTWO 4294967296.0 |
104 | #endif |
105 | |
106 | static inline double CoinCpuTime() |
107 | { |
108 | double cpu_temp; |
109 | #if defined(_MSC_VER) || defined(__MSVCRT__) |
110 | #ifdef HAVE_SDK |
111 | FILETIME creation; |
112 | FILETIME exit; |
113 | FILETIME kernel; |
114 | FILETIME user; |
115 | GetProcessTimes(GetCurrentProcess(), &creation, &exit, &kernel, &user); |
116 | double t = user.dwHighDateTime * TWO_TO_THE_THIRTYTWO + user.dwLowDateTime; |
117 | return t/10000000.0; |
118 | #else |
119 | unsigned int ticksnow; /* clock_t is same as int */ |
120 | ticksnow = (unsigned int)clock(); |
121 | cpu_temp = (double)((double)ticksnow/CLOCKS_PER_SEC); |
122 | #endif |
123 | |
124 | #else |
125 | struct rusage usage; |
126 | # ifdef ZEROFAULT |
127 | usage.ru_utime.tv_sec = 0 ; |
128 | usage.ru_utime.tv_usec = 0 ; |
129 | # endif |
130 | getrusage(RUSAGE_SELF,&usage); |
131 | cpu_temp = static_cast<double>(usage.ru_utime.tv_sec); |
132 | cpu_temp += 1.0e-6*(static_cast<double> (usage.ru_utime.tv_usec)); |
133 | #endif |
134 | return cpu_temp; |
135 | } |
136 | |
137 | //############################################################################# |
138 | |
139 | |
140 | |
141 | static inline double CoinSysTime() |
142 | { |
143 | double sys_temp; |
144 | #if defined(_MSC_VER) || defined(__MSVCRT__) |
145 | sys_temp = 0.0; |
146 | #else |
147 | struct rusage usage; |
148 | # ifdef ZEROFAULT |
149 | usage.ru_utime.tv_sec = 0 ; |
150 | usage.ru_utime.tv_usec = 0 ; |
151 | # endif |
152 | getrusage(RUSAGE_SELF,&usage); |
153 | sys_temp = static_cast<double>(usage.ru_stime.tv_sec); |
154 | sys_temp += 1.0e-6*(static_cast<double> (usage.ru_stime.tv_usec)); |
155 | #endif |
156 | return sys_temp; |
157 | } |
158 | |
159 | //############################################################################# |
160 | // On most systems SELF seems to include children threads, This is for when it doesn't |
161 | static inline double CoinCpuTimeJustChildren() |
162 | { |
163 | double cpu_temp; |
164 | #if defined(_MSC_VER) || defined(__MSVCRT__) |
165 | cpu_temp = 0.0; |
166 | #else |
167 | struct rusage usage; |
168 | # ifdef ZEROFAULT |
169 | usage.ru_utime.tv_sec = 0 ; |
170 | usage.ru_utime.tv_usec = 0 ; |
171 | # endif |
172 | getrusage(RUSAGE_CHILDREN,&usage); |
173 | cpu_temp = static_cast<double>(usage.ru_utime.tv_sec); |
174 | cpu_temp += 1.0e-6*(static_cast<double> (usage.ru_utime.tv_usec)); |
175 | #endif |
176 | return cpu_temp; |
177 | } |
178 | //############################################################################# |
179 | |
180 | #include <fstream> |
181 | |
182 | /** |
183 | This class implements a timer that also implements a tracing functionality. |
184 | |
185 | The timer stores the start time of the timer, for how much time it was set to |
186 | and when does it expire (start + limit = end). Queries can be made that tell |
187 | whether the timer is expired, is past an absolute time, is past a percentage |
188 | of the length of the timer. All times are given in seconds, but as double |
189 | numbers, so there can be fractional values. |
190 | |
191 | The timer can also be initialized with a stream and a specification whether |
192 | to write to or read from the stream. In the former case the result of every |
193 | query is written into the stream, in the latter case timing is not tested at |
194 | all, rather the supposed result is read out from the stream. This makes it |
195 | possible to exactly retrace time sensitive program execution. |
196 | */ |
197 | class CoinTimer |
198 | { |
199 | private: |
200 | /// When the timer was initialized/reset/restarted |
201 | double start; |
202 | /// |
203 | double limit; |
204 | double end; |
205 | #ifdef COIN_COMPILE_WITH_TRACING |
206 | std::fstream* stream; |
207 | bool write_stream; |
208 | #endif |
209 | |
210 | private: |
211 | #ifdef COIN_COMPILE_WITH_TRACING |
212 | inline bool evaluate(bool b_tmp) const { |
213 | int i_tmp = b_tmp; |
214 | if (stream) { |
215 | if (write_stream) |
216 | (*stream) << i_tmp << "\n" ; |
217 | else |
218 | (*stream) >> i_tmp; |
219 | } |
220 | return i_tmp; |
221 | } |
222 | inline double evaluate(double d_tmp) const { |
223 | if (stream) { |
224 | if (write_stream) |
225 | (*stream) << d_tmp << "\n" ; |
226 | else |
227 | (*stream) >> d_tmp; |
228 | } |
229 | return d_tmp; |
230 | } |
231 | #else |
232 | inline bool evaluate(const bool b_tmp) const { |
233 | return b_tmp; |
234 | } |
235 | inline double evaluate(const double d_tmp) const { |
236 | return d_tmp; |
237 | } |
238 | #endif |
239 | |
240 | public: |
241 | /// Default constructor creates a timer with no time limit and no tracing |
242 | CoinTimer() : |
243 | start(0), limit(1e100), end(1e100) |
244 | #ifdef COIN_COMPILE_WITH_TRACING |
245 | , stream(0), write_stream(true) |
246 | #endif |
247 | {} |
248 | |
249 | /// Create a timer with the given time limit and with no tracing |
250 | CoinTimer(double lim) : |
251 | start(CoinCpuTime()), limit(lim), end(start+lim) |
252 | #ifdef COIN_COMPILE_WITH_TRACING |
253 | , stream(0), write_stream(true) |
254 | #endif |
255 | {} |
256 | |
257 | #ifdef COIN_COMPILE_WITH_TRACING |
258 | /** Create a timer with no time limit and with writing/reading the trace |
259 | to/from the given stream, depending on the argument \c write. */ |
260 | CoinTimer(std::fstream* s, bool write) : |
261 | start(0), limit(1e100), end(1e100), |
262 | stream(s), write_stream(write) {} |
263 | |
264 | /** Create a timer with the given time limit and with writing/reading the |
265 | trace to/from the given stream, depending on the argument \c write. */ |
266 | CoinTimer(double lim, std::fstream* s, bool w) : |
267 | start(CoinCpuTime()), limit(lim), end(start+lim), |
268 | stream(s), write_stream(w) {} |
269 | #endif |
270 | |
271 | /// Restart the timer (keeping the same time limit) |
272 | inline void restart() { start=CoinCpuTime(); end=start+limit; } |
273 | /// An alternate name for \c restart() |
274 | inline void reset() { restart(); } |
275 | /// Reset (and restart) the timer and change its time limit |
276 | inline void reset(double lim) { limit=lim; restart(); } |
277 | |
278 | /** Return whether the given percentage of the time limit has elapsed since |
279 | the timer was started */ |
280 | inline bool isPastPercent(double pct) const { |
281 | return evaluate(start + limit * pct < CoinCpuTime()); |
282 | } |
283 | /** Return whether the given amount of time has elapsed since the timer was |
284 | started */ |
285 | inline bool isPast(double lim) const { |
286 | return evaluate(start + lim < CoinCpuTime()); |
287 | } |
288 | /** Return whether the originally specified time limit has passed since the |
289 | timer was started */ |
290 | inline bool isExpired() const { |
291 | return evaluate(end < CoinCpuTime()); |
292 | } |
293 | |
294 | /** Return how much time is left on the timer */ |
295 | inline double timeLeft() const { |
296 | return evaluate(end - CoinCpuTime()); |
297 | } |
298 | |
299 | /** Return how much time has elapsed */ |
300 | inline double timeElapsed() const { |
301 | return evaluate(CoinCpuTime() - start); |
302 | } |
303 | |
304 | inline void setLimit(double l) { |
305 | limit = l; |
306 | return; |
307 | } |
308 | }; |
309 | |
310 | #endif |
311 | |