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