Crypto++  5.6.3
Free C++ class library of cryptographic schemes
hrtimer.cpp
1 // hrtimer.cpp - written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "hrtimer.h"
5 #include "misc.h"
6 #include <stddef.h> // for NULL
7 #include <time.h>
8 
9 #if defined(CRYPTOPP_WIN32_AVAILABLE)
10 #include <windows.h>
11 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
12 #include <sys/time.h>
13 #include <sys/times.h>
14 #include <unistd.h>
15 #endif
16 
17 #include <assert.h>
18 
19 NAMESPACE_BEGIN(CryptoPP)
20 
21 #ifndef CRYPTOPP_IMPORTS
22 
23 double TimerBase::ConvertTo(TimerWord t, Unit unit)
24 {
25  static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000};
26 
27  // When 'unit' is an enum 'Unit', a Clang warning is generated.
28  assert(static_cast<unsigned int>(unit) < COUNTOF(unitsPerSecondTable));
29  return (double)CRYPTOPP_VC6_INT64 t * unitsPerSecondTable[unit] / CRYPTOPP_VC6_INT64 TicksPerSecond();
30 }
31 
32 void TimerBase::StartTimer()
33 {
34  m_last = m_start = GetCurrentTimerValue();
35  m_started = true;
36 }
37 
38 double TimerBase::ElapsedTimeAsDouble()
39 {
40  if (m_stuckAtZero)
41  return 0;
42 
43  if (m_started)
44  {
45  TimerWord now = GetCurrentTimerValue();
46  if (m_last < now) // protect against OS bugs where time goes backwards
47  m_last = now;
48  return ConvertTo(m_last - m_start, m_timerUnit);
49  }
50 
51  StartTimer();
52  return 0;
53 }
54 
55 unsigned long TimerBase::ElapsedTime()
56 {
57  double elapsed = ElapsedTimeAsDouble();
58  assert(elapsed <= ULONG_MAX);
59  return (unsigned long)elapsed;
60 }
61 
62 TimerWord Timer::GetCurrentTimerValue()
63 {
64 #if defined(CRYPTOPP_WIN32_AVAILABLE)
65  // Use the first union member to avoid an uninitialized warning
66  LARGE_INTEGER now = {0,0};
67  if (!QueryPerformanceCounter(&now))
68  throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError()));
69  return now.QuadPart;
70 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
71  timeval now;
72  gettimeofday(&now, NULL);
73  return (TimerWord)now.tv_sec * 1000000 + now.tv_usec;
74 #else
75  // clock_t now;
76  return clock();
77 #endif
78 }
79 
80 TimerWord Timer::TicksPerSecond()
81 {
82 #if defined(CRYPTOPP_WIN32_AVAILABLE)
83  // Use the second union member to avoid an uninitialized warning
84  static LARGE_INTEGER freq = {0,0};
85  if (freq.QuadPart == 0)
86  {
87  if (!QueryPerformanceFrequency(&freq))
88  throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
89  }
90  return freq.QuadPart;
91 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
92  return 1000000;
93 #else
94  return CLOCKS_PER_SEC;
95 #endif
96 }
97 
98 #endif // #ifndef CRYPTOPP_IMPORTS
99 
100 TimerWord ThreadUserTimer::GetCurrentTimerValue()
101 {
102 #if defined(CRYPTOPP_WIN32_AVAILABLE)
103  static bool getCurrentThreadImplemented = true;
104  if (getCurrentThreadImplemented)
105  {
106  FILETIME now, ignored;
107  if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now))
108  {
109  DWORD lastError = GetLastError();
110  if (lastError == ERROR_CALL_NOT_IMPLEMENTED)
111  {
112  getCurrentThreadImplemented = false;
113  goto GetCurrentThreadNotImplemented;
114  }
115  throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: GetThreadTimes failed with error " + IntToString(lastError));
116  }
117  return now.dwLowDateTime + ((TimerWord)now.dwHighDateTime << 32);
118  }
119 GetCurrentThreadNotImplemented:
120  return (TimerWord)clock() * (10*1000*1000 / CLOCKS_PER_SEC);
121 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
122  tms now;
123  times(&now);
124  return now.tms_utime;
125 #else
126  return clock();
127 #endif
128 }
129 
130 TimerWord ThreadUserTimer::TicksPerSecond()
131 {
132 #if defined(CRYPTOPP_WIN32_AVAILABLE)
133  return 10*1000*1000;
134 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
135  static const long ticksPerSecond = sysconf(_SC_CLK_TCK);
136  return ticksPerSecond;
137 #else
138  return CLOCKS_PER_SEC;
139 #endif
140 }
141 
142 NAMESPACE_END
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:139
Utility functions for the Crypto++ library.
Some other error occurred not belonging to other categories.
Definition: cryptlib.h:158
#define COUNTOF(arr)
Counts elements in an array.
Definition: misc.h:140
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:460
Crypto++ library namespace.