annotate src/win32/PerfTimer.h @ 1:f9f4f1b99eed

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