hrtimer.cpp

00001 // hrtimer.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "hrtimer.h"
00005 #include "misc.h"
00006 #include <stddef.h>             // for NULL
00007 #include <time.h>
00008 
00009 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00010 #include <windows.h>
00011 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00012 #include <sys/time.h>
00013 #include <sys/times.h>
00014 #include <unistd.h>
00015 #endif
00016 
00017 #include <assert.h>
00018 
00019 NAMESPACE_BEGIN(CryptoPP)
00020 
00021 double TimerBase::ConvertTo(TimerWord t, Unit unit)
00022 {
00023         static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000};
00024 
00025         assert(unit < sizeof(unitsPerSecondTable) / sizeof(unitsPerSecondTable[0]));
00026 #if defined(_MSC_VER) && (_MSC_VER < 1300)
00027         // MSVC 6 workaround
00028         return (double)(__int64)t * unitsPerSecondTable[unit] / (__int64)TicksPerSecond();
00029 #else
00030         return (double)t * unitsPerSecondTable[unit] / TicksPerSecond();
00031 #endif
00032                 
00033 }
00034 
00035 void TimerBase::StartTimer()
00036 {
00037         m_last = m_start = GetCurrentTimerValue();
00038         m_started = true;
00039 }
00040 
00041 double TimerBase::ElapsedTimeAsDouble()
00042 {
00043         if (m_stuckAtZero)
00044                 return 0;
00045 
00046         if (m_started)
00047         {
00048                 TimerWord now = GetCurrentTimerValue();
00049                 if (m_last < now)       // protect against OS bugs where time goes backwards
00050                         m_last = now;
00051                 return ConvertTo(m_last - m_start, m_timerUnit);
00052         }
00053 
00054         StartTimer();
00055         return 0;
00056 }
00057 
00058 unsigned long TimerBase::ElapsedTime()
00059 {
00060         double elapsed = ElapsedTimeAsDouble();
00061         assert(elapsed <= ULONG_MAX);
00062         return (unsigned long)elapsed;
00063 }
00064 
00065 TimerWord ThreadUserTimer::GetCurrentTimerValue()
00066 {
00067 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00068         static bool getCurrentThreadImplemented = true;
00069         if (getCurrentThreadImplemented)
00070         {
00071                 FILETIME now, ignored;
00072                 if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now))
00073                 {
00074                         DWORD lastError = GetLastError();
00075                         if (lastError == ERROR_CALL_NOT_IMPLEMENTED)
00076                         {
00077                                 getCurrentThreadImplemented = false;
00078                                 goto GetCurrentThreadNotImplemented;
00079                         }
00080                         throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: GetThreadTimes failed with error " + IntToString(lastError));
00081                 }
00082                 return now.dwLowDateTime + ((TimerWord)now.dwHighDateTime << 32);
00083         }
00084 GetCurrentThreadNotImplemented:
00085         return (TimerWord)clock() * (10*1000*1000 / CLOCKS_PER_SEC);
00086 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00087         tms now;
00088         times(&now);
00089         return now.tms_utime;
00090 #else
00091         return clock();
00092 #endif
00093 }
00094 
00095 TimerWord ThreadUserTimer::TicksPerSecond()
00096 {
00097 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00098         return 10*1000*1000;
00099 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00100         static const long ticksPerSecond = sysconf(_SC_CLK_TCK);
00101         return ticksPerSecond;
00102 #else
00103         return CLOCKS_PER_SEC;
00104 #endif
00105 }
00106 
00107 #ifdef HIGHRES_TIMER_AVAILABLE
00108 
00109 TimerWord Timer::GetCurrentTimerValue()
00110 {
00111 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00112         LARGE_INTEGER now;
00113         if (!QueryPerformanceCounter(&now))
00114                 throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError()));
00115         return now.QuadPart;
00116 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00117         timeval now;
00118         gettimeofday(&now, NULL);
00119         return (TimerWord)now.tv_sec * 1000000 + now.tv_usec;
00120 #endif
00121 }
00122 
00123 TimerWord Timer::TicksPerSecond()
00124 {
00125 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00126         static LARGE_INTEGER freq = {0};
00127         if (freq.QuadPart == 0)
00128         {
00129                 if (!QueryPerformanceFrequency(&freq))
00130                         throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
00131         }
00132         return freq.QuadPart;
00133 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00134         return 1000000;
00135 #endif
00136 }
00137 
00138 #endif  // HIGHRES_TIMER_AVAILABLE
00139 
00140 NAMESPACE_END

Generated on Sat Dec 23 02:07:07 2006 for Crypto++ by  doxygen 1.5.1-p1