- Main Page
- Namespaces
- Classes
- Files

# 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