- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# 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