SAGA Adaptor CPI v.1.0
high_resolution_timer.hpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines