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 #ifndef CRYPTOPP_IMPORTS
00022 
00023 double TimerBase::ConvertTo(TimerWord t, Unit unit)
00024 {
00025         static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000};
00026 
00027         assert(unit < sizeof(unitsPerSecondTable) / sizeof(unitsPerSecondTable[0]));
00028         return (double)CRYPTOPP_VC6_INT64 t * unitsPerSecondTable[unit] / CRYPTOPP_VC6_INT64 TicksPerSecond();
00029 }
00030 
00031 void TimerBase::StartTimer()
00032 {
00033         m_last = m_start = GetCurrentTimerValue();
00034         m_started = true;
00035 }
00036 
00037 double TimerBase::ElapsedTimeAsDouble()
00038 {
00039         if (m_stuckAtZero)
00040                 return 0;
00041 
00042         if (m_started)
00043         {
00044                 TimerWord now = GetCurrentTimerValue();
00045                 if (m_last < now)       // protect against OS bugs where time goes backwards
00046                         m_last = now;
00047                 return ConvertTo(m_last - m_start, m_timerUnit);
00048         }
00049 
00050         StartTimer();
00051         return 0;
00052 }
00053 
00054 unsigned long TimerBase::ElapsedTime()
00055 {
00056         double elapsed = ElapsedTimeAsDouble();
00057         assert(elapsed <= ULONG_MAX);
00058         return (unsigned long)elapsed;
00059 }
00060 
00061 TimerWord Timer::GetCurrentTimerValue()
00062 {
00063 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00064         LARGE_INTEGER now;
00065         if (!QueryPerformanceCounter(&now))
00066                 throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError()));
00067         return now.QuadPart;
00068 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00069         timeval now;
00070         gettimeofday(&now, NULL);
00071         return (TimerWord)now.tv_sec * 1000000 + now.tv_usec;
00072 #else
00073         clock_t now;
00074         return clock();
00075 #endif
00076 }
00077 
00078 TimerWord Timer::TicksPerSecond()
00079 {
00080 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00081         static LARGE_INTEGER freq = {0};
00082         if (freq.QuadPart == 0)
00083         {
00084                 if (!QueryPerformanceFrequency(&freq))
00085                         throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
00086         }
00087         return freq.QuadPart;
00088 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00089         return 1000000;
00090 #else
00091         return CLOCKS_PER_SEC;
00092 #endif
00093 }
00094 
00095 #endif  // #ifndef CRYPTOPP_IMPORTS
00096 
00097 TimerWord ThreadUserTimer::GetCurrentTimerValue()
00098 {
00099 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00100         static bool getCurrentThreadImplemented = true;
00101         if (getCurrentThreadImplemented)
00102         {
00103                 FILETIME now, ignored;
00104                 if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now))
00105                 {
00106                         DWORD lastError = GetLastError();
00107                         if (lastError == ERROR_CALL_NOT_IMPLEMENTED)
00108                         {
00109                                 getCurrentThreadImplemented = false;
00110                                 goto GetCurrentThreadNotImplemented;
00111                         }
00112                         throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: GetThreadTimes failed with error " + IntToString(lastError));
00113                 }
00114                 return now.dwLowDateTime + ((TimerWord)now.dwHighDateTime << 32);
00115         }
00116 GetCurrentThreadNotImplemented:
00117         return (TimerWord)clock() * (10*1000*1000 / CLOCKS_PER_SEC);
00118 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00119         tms now;
00120         times(&now);
00121         return now.tms_utime;
00122 #else
00123         return clock();
00124 #endif
00125 }
00126 
00127 TimerWord ThreadUserTimer::TicksPerSecond()
00128 {
00129 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00130         return 10*1000*1000;
00131 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00132         static const long ticksPerSecond = sysconf(_SC_CLK_TCK);
00133         return ticksPerSecond;
00134 #else
00135         return CLOCKS_PER_SEC;
00136 #endif
00137 }
00138 
00139 NAMESPACE_END

Generated on Fri Jun 1 11:11:21 2007 for Crypto++ by  doxygen 1.5.2