SAGA Adaptor CPI v.1.0
|
00001 // Copyright (c) 2005-2009 Hartmut Kaiser 00002 // 00003 // Distributed under the Boost Software License, Version 1.0. (See accompanying 00004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 00005 00006 #if !defined(SAGA_UTIL_HIGH_RESOLUTION_TIMER_MAR_24_2008_1222PM) 00007 #define SAGA_UTIL_HIGH_RESOLUTION_TIMER_MAR_24_2008_1222PM 00008 00009 #include <boost/config.hpp> 00010 #include <boost/throw_exception.hpp> 00011 00012 #if defined(BOOST_HAS_UNISTD_H) 00013 #include <unistd.h> 00014 #endif 00015 #include <time.h> 00016 00017 #if defined(BOOST_WINDOWS) 00018 00019 #include <stdexcept> 00020 #include <limits> 00021 #include <windows.h> 00022 00023 namespace saga { namespace adaptors { namespace utils 00024 { 00026 // 00027 // high_resolution_timer 00028 // A timer object measures elapsed time. 00029 // CAUTION: Windows only! 00030 // 00032 class high_resolution_timer 00033 { 00034 public: 00035 high_resolution_timer() 00036 { 00037 restart(); 00038 } 00039 00040 high_resolution_timer(double t) 00041 { 00042 LARGE_INTEGER frequency; 00043 if (!QueryPerformanceFrequency(&frequency)) 00044 boost::throw_exception(std::runtime_error("Couldn't acquire frequency")); 00045 00046 start_time.QuadPart = (LONGLONG)(t * frequency.QuadPart); 00047 } 00048 00049 high_resolution_timer(high_resolution_timer const& rhs) 00050 : start_time(rhs.start_time) 00051 { 00052 } 00053 00054 static double now() 00055 { 00056 SYSTEMTIME st; 00057 GetSystemTime(&st); 00058 00059 FILETIME ft; 00060 SystemTimeToFileTime(&st, &ft); 00061 00062 LARGE_INTEGER now; 00063 now.LowPart = ft.dwLowDateTime; 00064 now.HighPart = ft.dwHighDateTime; 00065 00066 // FileTime is in 100ns increments, result needs to be in [s] 00067 return now.QuadPart * 1e-7; 00068 } 00069 00070 void restart() 00071 { 00072 if (!QueryPerformanceCounter(&start_time)) 00073 boost::throw_exception(std::runtime_error("Couldn't initialize start_time")); 00074 } 00075 double elapsed() const // return elapsed time in seconds 00076 { 00077 LARGE_INTEGER now; 00078 if (!QueryPerformanceCounter(&now)) 00079 boost::throw_exception(std::runtime_error("Couldn't get current time")); 00080 00081 LARGE_INTEGER frequency; 00082 if (!QueryPerformanceFrequency(&frequency)) 00083 boost::throw_exception(std::runtime_error("Couldn't acquire frequency")); 00084 00085 return double(now.QuadPart - start_time.QuadPart) / frequency.QuadPart; 00086 } 00087 00088 double elapsed_max() const // return estimated maximum value for elapsed() 00089 { 00090 LARGE_INTEGER frequency; 00091 if (!QueryPerformanceFrequency(&frequency)) 00092 boost::throw_exception(std::runtime_error("Couldn't acquire frequency")); 00093 00094 return double((std::numeric_limits<LONGLONG>::max)() - start_time.QuadPart) / 00095 double(frequency.QuadPart); 00096 } 00097 00098 double elapsed_min() const // return minimum value for elapsed() 00099 { 00100 LARGE_INTEGER frequency; 00101 if (!QueryPerformanceFrequency(&frequency)) 00102 boost::throw_exception(std::runtime_error("Couldn't acquire frequency")); 00103 00104 return 1.0 / frequency.QuadPart; 00105 } 00106 00107 private: 00108 LARGE_INTEGER start_time; 00109 }; 00110 00111 }}} 00112 00113 #elif defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(_POSIX_THREAD_CPUTIME) 00114 00115 #if _POSIX_THREAD_CPUTIME > 0 // timer always supported 00116 00117 namespace saga { namespace adaptors { namespace utils 00118 { 00119 00121 // 00122 // high_resolution_timer 00123 // A timer object measures elapsed time. 00124 // 00126 class high_resolution_timer 00127 { 00128 public: 00129 high_resolution_timer() 00130 { 00131 start_time.tv_sec = 0; 00132 start_time.tv_nsec = 0; 00133 00134 restart(); 00135 } 00136 00137 high_resolution_timer(double t) 00138 { 00139 start_time.tv_sec = time_t(t); 00140 start_time.tv_nsec = (t - start_time.tv_sec) * 1e9; 00141 } 00142 00143 high_resolution_timer(high_resolution_timer const& rhs) 00144 : start_time(rhs.start_time) 00145 { 00146 } 00147 00148 static double now() 00149 { 00150 timespec now; 00151 if (-1 == clock_gettime(CLOCK_REALTIME, &now)) 00152 boost::throw_exception(std::runtime_error("Couldn't get current time")); 00153 return double(now.tv_sec) + double(now.tv_nsec) * 1e-9; 00154 } 00155 00156 void restart() 00157 { 00158 if (-1 == clock_gettime(CLOCK_REALTIME, &start_time)) 00159 boost::throw_exception(std::runtime_error("Couldn't initialize start_time")); 00160 } 00161 double elapsed() const // return elapsed time in seconds 00162 { 00163 timespec now; 00164 if (-1 == clock_gettime(CLOCK_REALTIME, &now)) 00165 boost::throw_exception(std::runtime_error("Couldn't get current time")); 00166 00167 if (now.tv_sec == start_time.tv_sec) 00168 return double(now.tv_nsec - start_time.tv_nsec) * 1e-9; 00169 00170 return double(now.tv_sec - start_time.tv_sec) + 00171 (double(now.tv_nsec - start_time.tv_nsec) * 1e-9); 00172 } 00173 00174 double elapsed_max() const // return estimated maximum value for elapsed() 00175 { 00176 return double((std::numeric_limits<time_t>::max)() - start_time.tv_sec); 00177 } 00178 00179 double elapsed_min() const // return minimum value for elapsed() 00180 { 00181 timespec resolution; 00182 if (-1 == clock_getres(CLOCK_REALTIME, &resolution)) 00183 boost::throw_exception(std::runtime_error("Couldn't get resolution")); 00184 return double(resolution.tv_sec + resolution.tv_nsec * 1e-9); 00185 } 00186 00187 private: 00188 timespec start_time; 00189 }; 00190 00191 }}} 00192 00193 #else // _POSIX_THREAD_CPUTIME > 0 00194 00195 #include <boost/timer.hpp> 00196 00197 // availability of high performance timers must be checked at runtime 00198 namespace saga { namespace adaptors { namespace utils 00199 { 00201 // 00202 // high_resolution_timer 00203 // A timer object measures elapsed time. 00204 // 00206 class high_resolution_timer 00207 { 00208 public: 00209 high_resolution_timer() 00210 : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0) 00211 { 00212 if (!use_backup) { 00213 start_time.tv_sec = 0; 00214 start_time.tv_nsec = 0; 00215 } 00216 restart(); 00217 } 00218 00219 high_resolution_timer(double t) 00220 : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0) 00221 { 00222 if (!use_backup) { 00223 start_time.tv_sec = time_t(t); 00224 start_time.tv_nsec = (t - start_time.tv_sec) * 1e9; 00225 } 00226 } 00227 00228 high_resolution_timer(high_resolution_timer const& rhs) 00229 : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0), 00230 start_time(rhs.start_time) 00231 { 00232 } 00233 00234 static double now() 00235 { 00236 if (sysconf(_SC_THREAD_CPUTIME) <= 0) 00237 return double(std::clock()); 00238 00239 timespec now; 00240 if (-1 == clock_gettime(CLOCK_REALTIME, &now)) 00241 boost::throw_exception(std::runtime_error("Couldn't get current time")); 00242 return double(now.tv_sec) + double(now.tv_nsec) * 1e-9; 00243 } 00244 00245 void restart() 00246 { 00247 if (use_backup) 00248 start_time_backup.restart(); 00249 else if (-1 == clock_gettime(CLOCK_REALTIME, &start_time)) 00250 boost::throw_exception(std::runtime_error("Couldn't initialize start_time")); 00251 } 00252 double elapsed() const // return elapsed time in seconds 00253 { 00254 if (use_backup) 00255 return start_time_backup.elapsed(); 00256 00257 timespec now; 00258 if (-1 == clock_gettime(CLOCK_REALTIME, &now)) 00259 boost::throw_exception(std::runtime_error("Couldn't get current time")); 00260 00261 if (now.tv_sec == start_time.tv_sec) 00262 return double(now.tv_nsec - start_time.tv_nsec) * 1e-9; 00263 00264 return double(now.tv_sec - start_time.tv_sec) + 00265 (double(now.tv_nsec - start_time.tv_nsec) * 1e-9); 00266 } 00267 00268 double elapsed_max() const // return estimated maximum value for elapsed() 00269 { 00270 if (use_backup) 00271 start_time_backup.elapsed_max(); 00272 00273 return double((std::numeric_limits<time_t>::max)() - start_time.tv_sec); 00274 } 00275 00276 double elapsed_min() const // return minimum value for elapsed() 00277 { 00278 if (use_backup) 00279 start_time_backup.elapsed_min(); 00280 00281 timespec resolution; 00282 if (-1 == clock_getres(CLOCK_REALTIME, &resolution)) 00283 boost::throw_exception(std::runtime_error("Couldn't get resolution")); 00284 return double(resolution.tv_sec + resolution.tv_nsec * 1e-9); 00285 } 00286 00287 private: 00288 bool use_backup; 00289 timespec start_time; 00290 boost::timer start_time_backup; 00291 }; 00292 00293 }}} 00294 00295 #endif // _POSIX_THREAD_CPUTIME > 0 00296 00297 #else // !defined(BOOST_WINDOWS) && (!defined(_POSIX_TIMERS) 00298 // || _POSIX_TIMERS <= 0 00299 // || !defined(_POSIX_THREAD_CPUTIME) 00300 // || _POSIX_THREAD_CPUTIME <= 0) 00301 00302 // For platforms other than Windows or Linux, simply fall back to boost::timer 00303 #include <boost/timer.hpp> 00304 00305 namespace saga { namespace adaptors { namespace utils 00306 { 00307 struct high_resolution_timer 00308 : boost::timer 00309 { 00310 static double now() 00311 { 00312 return double(std::clock()); 00313 } 00314 }; 00315 }}} 00316 00317 #endif 00318 00319 #endif 00320