1 // hrtimer.h - originally written and placed in the public domain by Wei Dai
2 
3 /// \file hrtimer.h
4 /// \brief Classes for timers
5 
6 #ifndef CRYPTOPP_HRTIMER_H
7 #define CRYPTOPP_HRTIMER_H
8 
9 #include "config.h"
10 
11 #if !defined(HIGHRES_TIMER_AVAILABLE) || (defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE))
12 #include <time.h>
13 #endif
14 
15 NAMESPACE_BEGIN(CryptoPP)
16 
17 #ifdef HIGHRES_TIMER_AVAILABLE
18 	/// \brief TimerWord is a 64-bit word
19 	typedef word64 TimerWord;
20 #else
21 	/// \brief TimerWord is a clock_t
22 	typedef clock_t TimerWord;
23 #endif
24 
25 /// \brief Base class for timers
26 /// \sa ThreadUserTimer, Timer
27 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TimerBase
28 {
29 public:
30 	/// \brief Unit of measure
31 	/// \details Unit selects the unit of measure as returned by functions
32 	///  ElapsedTimeAsDouble() and ElapsedTime().
33 	/// \sa ElapsedTimeAsDouble, ElapsedTime
34 	enum Unit {
35 		/// \brief Timer unit is seconds
36 		/// \details All timers support seconds
37 		SECONDS = 0,
38 		/// \brief Timer unit is milliseconds
39 		/// \details All timers support milliseconds
40 		MILLISECONDS,
41 		/// \brief Timer unit is microseconds
42 		/// \details The timer requires hardware support microseconds
43 		MICROSECONDS,
44 		/// \brief Timer unit is nanoseconds
45 		/// \details The timer requires hardware support nanoseconds
46 		NANOSECONDS
47 	};
48 
49 	/// \brief Construct a TimerBase
50 	/// \param unit the unit of measure
51 	/// \param stuckAtZero flag
TimerBase(Unit unit,bool stuckAtZero)52 	TimerBase(Unit unit, bool stuckAtZero)
53 		: m_timerUnit(unit), m_stuckAtZero(stuckAtZero), m_started(false)
54 		, m_start(0), m_last(0) {}
55 
56 	/// \brief Retrieve the current timer value
57 	/// \return the current timer value
58 	virtual TimerWord GetCurrentTimerValue() =0;
59 
60 	/// \brief Retrieve ticks per second
61 	/// \return ticks per second
62 	/// \details TicksPerSecond() is not the timer resolution. It is a
63 	///  conversion factor into seconds.
64 	virtual TimerWord TicksPerSecond() =0;
65 
66 	/// \brief Start the timer
67 	void StartTimer();
68 
69 	/// \brief Retrieve the elapsed time
70 	/// \return the elapsed time as a double
71 	/// \details The return value of ElapsedTimeAsDouble() depends upon
72 	///  the Unit selected during construction of the timer. For example,
73 	///  if <tt>Unit = SECONDS</tt> and ElapsedTimeAsDouble() returns 3,
74 	///  then the timer has run for 3 seconds. If
75 	///  <tt>Unit = MILLISECONDS</tt> and ElapsedTimeAsDouble() returns
76 	///  3000, then the timer has run for 3 seconds.
77 	/// \sa Unit, ElapsedTime
78 	double ElapsedTimeAsDouble();
79 
80 	/// \brief Retrieve the elapsed time
81 	/// \return the elapsed time as an unsigned long
82 	/// \details The return value of ElapsedTime() depends upon the
83 	///  Unit selected during construction of the timer. For example, if
84 	///  <tt>Unit = SECONDS</tt> and ElapsedTime() returns 3, then
85 	///  the timer has run for 3 seconds. If <tt>Unit = MILLISECONDS</tt>
86 	///  and ElapsedTime() returns 3000, then the timer has run for 3
87 	///  seconds.
88 	/// \sa Unit, ElapsedTimeAsDouble
89 	unsigned long ElapsedTime();
90 
91 private:
92 	double ConvertTo(TimerWord t, Unit unit);
93 
94 	Unit m_timerUnit;	// HPUX workaround: m_unit is a system macro on HPUX
95 	bool m_stuckAtZero, m_started;
96 	TimerWord m_start, m_last;
97 };
98 
99 /// \brief Measure CPU time spent executing instructions of this thread
100 /// \details ThreadUserTimer requires support of the OS. On Unix-based it
101 ///  reports process time. On Windows NT or later desktops and servers it
102 ///  reports thread times with performance counter precision.. On Windows
103 ///  Phone and Windows Store it reports wall clock time with performance
104 ///  counter precision. On all others it reports wall clock time.
105 /// \note ThreadUserTimer only works correctly on Windows NT or later
106 ///  desktops and servers.
107 /// \sa Timer
108 class ThreadUserTimer : public TimerBase
109 {
110 public:
111 	/// \brief Construct a ThreadUserTimer
112 	/// \param unit the unit of measure
113 	/// \param stuckAtZero flag
TimerBase(unit,stuckAtZero)114 	ThreadUserTimer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {}
115 	TimerWord GetCurrentTimerValue();
116 	TimerWord TicksPerSecond();
117 };
118 
119 /// \brief High resolution timer
120 /// \sa ThreadUserTimer
121 class CRYPTOPP_DLL Timer : public TimerBase
122 {
123 public:
124 	/// \brief Construct a Timer
125 	/// \param unit the unit of measure
126 	/// \param stuckAtZero flag
TimerBase(unit,stuckAtZero)127 	Timer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false)	: TimerBase(unit, stuckAtZero) {}
128 	TimerWord GetCurrentTimerValue();
129 	TimerWord TicksPerSecond();
130 };
131 
132 NAMESPACE_END
133 
134 #endif
135