view src/win32/PerfTimer.h @ 5:8fe0c57e53d2

concentrating on lua first
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:39:40 -0600
parents f9f4f1b99eed
children
line wrap: on
line source
1 // CPerfTimer - a simple Win32 performance counter wrapper
2 // by Dean Wyant dwyant@mindspring.com
4 /*
6 This class is simple to use. Just declare a variable(s) as type CPerfTimer,
7 call Start() to start timimg and call Stop() to stop timimg. You can pause a
8 timer by calling Stop() and then you can call Start() to resume. Retrieve the
9 elapsed time by calling an Elapsed..() function. Assignment, addition,
10 subtraction and comparison are supported. There are a few information calls
11 available also. All calls except Start and Stop can be performed on a timer
12 without stopping it.
14 */
16 #ifndef __PERFTIMER_H__
17 #define __PERFTIMER_H__
19 class CPerfTimer
20 {
21 public:
22 CPerfTimer(BOOL bStart = FALSE) {Init(bStart);}
24 CPerfTimer(const CPerfTimer& Src);
26 virtual ~CPerfTimer() {;}
28 void Start(BOOL bReset = FALSE); // Start from current value or optionally from 0
29 void Stop(); // Stop timing. Use Start afterwards to continue.
31 BOOL IsRunning(); // Returns FALSE if stopped.
33 BOOL IsSupported(); // Returns FALSE if performance counter not supported.
34 // Call after constructing at least one CPerfTimer
36 const double Resolution(); // Returns timer resolution in seconds
37 const double Resolutionms(); // Returns timer resolution in milliseconds
38 const double Resolutionus(); // Returns timer resolution in microseconds
40 const double Elapsed(); // Returns elapsed time in seconds
41 const double Elapsedms(); // Returns elapsed time in milliseconds
42 const double Elapsedus(); // Returns elapsed time in microseconds
44 const CPerfTimer& operator=(const CPerfTimer& Src); // Assignment operator
46 // Math operators
47 CPerfTimer operator+(const CPerfTimer& Src) const;
48 CPerfTimer operator-(const CPerfTimer& Src) const;
49 const CPerfTimer& operator+=(const CPerfTimer& Src);
50 const CPerfTimer& operator-=(const CPerfTimer& Src);
51 // For time in seconds
52 CPerfTimer operator+(const double Secs) const;
53 CPerfTimer operator-(const double Secs) const;
54 const CPerfTimer& operator+=(const double Secs);
55 const CPerfTimer& operator-=(const double Secs);
57 // Boolean comparison operators
58 BOOL operator<(const CPerfTimer& Src);
59 BOOL operator>(const CPerfTimer& Src);
60 BOOL operator<=(const CPerfTimer& Src);
61 BOOL operator>=(const CPerfTimer& Src);
62 // For time in seconds
63 BOOL operator<(const double Secs);
64 BOOL operator>(const double Secs);
65 BOOL operator<=(const double Secs);
66 BOOL operator>=(const double Secs);
68 virtual void Lock() const {;} // Override for thread safe operation
69 virtual void Unlock() const {;} // Override for thread safe operation
70 protected:
71 void Init(BOOL bStart);
72 void Copy(const CPerfTimer& Src);
74 private:
75 __int64 m_Start;
76 static __int64 m_Freq; // does not change while system is running
77 static __int64 m_Adjust; // Adjustment time it takes to Start and Stop
78 };
80 class CPerfTimerT : public CPerfTimer
81 { // You only need to use types of this class if a timer is going to be shared between threads
82 public:
83 CPerfTimerT(BOOL bStart = FALSE)
84 {
85 m_hMutex = CreateMutex(NULL,FALSE,"");
86 Init(bStart);
87 }
89 CPerfTimerT(const CPerfTimerT& Src)
90 {
91 m_hMutex = CreateMutex(NULL,FALSE,"");
92 Copy(Src);
93 }
95 CPerfTimerT(const CPerfTimer& Src)
96 {
97 m_hMutex = CreateMutex(NULL,FALSE,"");
98 Copy(Src);
99 }
101 virtual ~CPerfTimerT()
102 { CloseHandle(m_hMutex); }
104 const CPerfTimerT& operator=(const CPerfTimerT& Src) // Assignment operator
105 {
106 Copy(Src);
107 return *this;
108 }
110 virtual void Lock() const { WaitForSingleObject(m_hMutex,10000); }
111 virtual void Unlock() const { ReleaseMutex(m_hMutex); }
112 private:
113 HANDLE m_hMutex;
114 };
116 inline void CPerfTimer::Init(BOOL bStart)
117 {
118 if (!m_Freq)
119 { // Initialization should only run once
120 QueryPerformanceFrequency((LARGE_INTEGER *)&m_Freq);
121 if (!m_Freq)
122 m_Freq = 1; // Timer will be useless but will not cause divide by zero
123 m_Start = 0;
124 m_Adjust = 0;
125 Start(); // Time a Stop
126 Stop();
127 m_Adjust = m_Start;
128 }
129 // This is the only part that normally runs
130 m_Start = 0;
131 if (bStart)
132 Start();
133 }
135 inline CPerfTimer::CPerfTimer(const CPerfTimer& Src)
136 {
137 Copy(Src);
138 }
140 inline void CPerfTimer::Copy(const CPerfTimer& Src)
141 {
142 if (&Src == this)
143 return; // avoid deadlock if someone tries to copy it to itself
144 Src.Lock();
145 Lock();
146 m_Start = Src.m_Start;
147 Unlock();
148 Src.Unlock();
149 }
151 inline void CPerfTimer::Start(BOOL bReset)
152 { // Start from current value or optionally from 0
153 __int64 i;
154 QueryPerformanceCounter((LARGE_INTEGER *)&i);
155 Lock();
156 if ((!bReset) && (m_Start < 0))
157 m_Start += i; // We are starting with an accumulated time
158 else
159 m_Start = i; // Starting from 0
160 Unlock();
161 }
163 inline void CPerfTimer::Stop()
164 { // Stop timing. Use Start afterwards to continue
165 Lock();
166 if (m_Start <= 0)
167 {
168 Unlock();
169 return; // Was not running
170 }
171 __int64 i;
172 QueryPerformanceCounter((LARGE_INTEGER *)&i);
173 m_Start += -i; // Stopped timer keeps elapsed timer ticks as a negative
174 if (m_Start < m_Adjust) // Do not overflow
175 m_Start -= m_Adjust; // Adjust for time timer code takes to run
176 else
177 m_Start = 0; // Stop must have been called directly after Start
178 Unlock();
179 }
181 inline BOOL CPerfTimer::IsRunning()
182 { // Returns FALSE if stopped.
183 Lock();
184 BOOL bRet = (m_Start > 0); // When < 0, holds elpased clicks
185 Unlock();
186 return bRet;
187 }
188 inline const double CPerfTimer::Elapsed()
189 { // Returns elapsed time in seconds
190 CPerfTimer Result(*this);
191 Result.Stop();
192 return (double)(-Result.m_Start)/(double)m_Freq;
193 }
195 inline const double CPerfTimer::Elapsedms()
196 { // Returns elapsed time in milliseconds
197 CPerfTimer Result(*this);
198 Result.Stop();
199 return (-Result.m_Start*1000.0)/(double)m_Freq;
200 }
202 inline const double CPerfTimer::Elapsedus()
203 { // Returns elapsed time in microseconds
204 CPerfTimer Result(*this);
206 return (-Result.m_Start * 1000000.0)/(double)m_Freq;
207 }
210 // Assignment operator
211 inline const CPerfTimer& CPerfTimer::operator=(const CPerfTimer& Src)
212 {
213 Copy(Src);
214 return *this;
215 }
218 // Math operators
219 inline CPerfTimer CPerfTimer::operator+(const CPerfTimer& Src) const
220 {
221 CPerfTimer Result(*this);
222 Result += Src;
223 return Result;
224 }
226 inline CPerfTimer CPerfTimer::operator-(const CPerfTimer& Src) const
227 {
228 CPerfTimer Result(*this);
229 Result -= Src;
230 return Result;
231 }
233 inline const CPerfTimer& CPerfTimer::operator+=(const CPerfTimer& Src)
234 {
235 CPerfTimer SrcStop(Src); // Temp is necessary in case Src is not stopped
236 SrcStop.Stop();
237 Lock();
238 m_Start += SrcStop.m_Start;
239 Unlock();
240 return *this;
241 }
243 inline const CPerfTimer& CPerfTimer::operator-=(const CPerfTimer& Src)
244 {
245 CPerfTimer SrcStop(Src); // Temp is necessary in case Src is not stopped
246 SrcStop.Stop();
247 Lock();
248 m_Start -= SrcStop.m_Start;
249 Unlock();
250 return *this;
251 }
253 // For time in seconds
254 inline CPerfTimer CPerfTimer::operator+(const double Secs) const
255 {
256 CPerfTimer Result(*this);
257 Result += Secs;
258 return Result;
259 }
261 inline CPerfTimer CPerfTimer::operator-(const double Secs) const
262 {
263 CPerfTimer Result(*this);
264 Result += Secs;
265 return Result;
266 }
268 inline const CPerfTimer& CPerfTimer::operator+=(const double Secs)
269 {
270 Lock();
271 m_Start -= (__int64)(Secs*(double)m_Freq);
272 Unlock();
273 return *this;
274 }
276 inline const CPerfTimer& CPerfTimer::operator-=(const double Secs)
277 {
278 Lock();
279 m_Start += (__int64)(Secs*(double)m_Freq);
280 Unlock();
281 return *this;
282 }
286 // Boolean comparison operators
287 inline BOOL CPerfTimer::operator<(const CPerfTimer& Src)
288 {
289 BOOL bRet;
290 CPerfTimer Temp(Src);
291 Lock();
292 if (m_Start <= 0)
293 {
294 Temp.Stop();
295 bRet = (m_Start > Temp.m_Start);
296 Unlock();
297 return bRet;
298 }
299 else
300 if (Temp.m_Start > 0)
301 {
302 bRet = (m_Start < Temp.m_Start);
303 Unlock();
304 return bRet;
305 }
306 else
307 {
308 Unlock();
309 CPerfTimer ThisStop(*this);
310 ThisStop.Stop();
311 return (ThisStop.m_Start > Temp.m_Start);
312 }
313 }
315 inline BOOL CPerfTimer::operator>(const CPerfTimer& Src)
316 {
317 BOOL bRet;
318 CPerfTimer Temp(Src);
319 Lock();
320 if (m_Start <= 0)
321 {
322 Temp.Stop();
323 bRet = (m_Start < Temp.m_Start);
324 Unlock();
325 return bRet;
326 }
327 else
328 if (Temp.m_Start > 0)
329 {
330 bRet = (m_Start > Temp.m_Start);
331 Unlock();
332 return bRet;
333 }
334 else
335 {
336 Unlock();
337 CPerfTimer ThisStop(*this);
338 ThisStop.Stop();
339 return (ThisStop.m_Start < Temp.m_Start);
340 }
341 }
343 inline BOOL CPerfTimer::operator<=(const CPerfTimer& Src)
344 {
345 return !(*this > Src);
346 }
348 inline BOOL CPerfTimer::operator>=(const CPerfTimer& Src)
349 {
350 return !(*this < Src);
351 }
353 // For time in seconds
354 inline BOOL CPerfTimer::operator<(const double Secs)
355 {
356 BOOL bRet;
357 Lock();
358 if (m_Start <= 0)
359 {
360 bRet = (m_Start > (__int64)(-Secs*(double)m_Freq));
361 Unlock();
362 return bRet;
363 }
364 else
365 {
366 Unlock();
367 CPerfTimer ThisStop(*this);
368 ThisStop.Stop();
369 return (ThisStop.m_Start > (__int64)(-Secs*(double)m_Freq));
370 }
371 }
373 inline BOOL CPerfTimer::operator>(const double Secs)
374 {
375 BOOL bRet;
376 Lock();
377 if (m_Start <= 0)
378 {
379 bRet = (m_Start < (__int64)(-Secs*(double)m_Freq));
380 Unlock();
381 return bRet;
382 }
383 else
384 {
385 Unlock();
386 CPerfTimer ThisStop(*this);
387 ThisStop.Stop();
388 return (ThisStop.m_Start < (__int64)(-Secs*(double)m_Freq));
389 }
390 }
392 inline BOOL CPerfTimer::operator<=(const double Secs)
393 {
394 return !(*this > Secs);
395 }
397 inline BOOL CPerfTimer::operator>=(const double Secs)
398 {
399 return !(*this < Secs);
400 }
403 #endif //__PERFTIMER_H__