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
43inline 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>
55inline 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
69inline 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
86inline 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
106static 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
141static 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
161static 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*/
197class CoinTimer
198{
199private:
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
210private:
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
240public:
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