Filter Library | Camera | Interface Physics |
00001 // CPerfTimer - a simple Win32 performance counter wrapper 00002 // by Dean Wyant dwyant@mindspring.com 00003 00004 /* 00005 00006 This class is simple to use. Just declare a variable(s) as type CPerfTimer, 00007 call Start() to start timimg and call Stop() to stop timimg. You can pause a 00008 timer by calling Stop() and then you can call Start() to resume. Retrieve the 00009 elapsed time by calling an Elapsed..() function. Assignment, addition, 00010 subtraction and comparison are supported. There are a few information calls 00011 available also. All calls except Start and Stop can be performed on a timer 00012 without stopping it. 00013 00014 */ 00015 00016 #ifndef __PERFTIMER_H__ 00017 #define __PERFTIMER_H__ 00018 00019 class CPerfTimer 00020 { 00021 public: 00022 CPerfTimer( BOOL bStart = FALSE ) { Init(bStart); } 00023 00024 CPerfTimer(const CPerfTimer& Src); 00025 00026 virtual ~CPerfTimer() {;} 00027 00028 void Start(BOOL bReset = FALSE); // Start from current value or optionally from 0 00029 void Stop(); // Stop timing. Use Start afterwards to continue. 00030 00031 BOOL IsRunning(); // Returns FALSE if stopped. 00032 00033 BOOL IsSupported(); // Returns FALSE if performance counter not supported. 00034 // Call after constructing at least one CPerfTimer 00035 00036 const double Resolution(); // Returns timer resolution in seconds 00037 const double Resolutionms(); // Returns timer resolution in milliseconds 00038 const double Resolutionus(); // Returns timer resolution in microseconds 00039 00040 const double Elapsed(); // Returns elapsed time in seconds 00041 const double Elapsedms(); // Returns elapsed time in milliseconds 00042 const double Elapsedus(); // Returns elapsed time in microseconds 00043 00044 const CPerfTimer& operator=(const CPerfTimer& Src); // Assignment operator 00045 00046 // Math operators 00047 CPerfTimer operator+(const CPerfTimer& Src) const; 00048 CPerfTimer operator-(const CPerfTimer& Src) const; 00049 const CPerfTimer& operator+=(const CPerfTimer& Src); 00050 const CPerfTimer& operator-=(const CPerfTimer& Src); 00051 // For time in seconds 00052 CPerfTimer operator+(const double Secs) const; 00053 CPerfTimer operator-(const double Secs) const; 00054 const CPerfTimer& operator+=(const double Secs); 00055 const CPerfTimer& operator-=(const double Secs); 00056 00057 // Boolean comparison operators 00058 BOOL operator<(const CPerfTimer& Src); 00059 BOOL operator>(const CPerfTimer& Src); 00060 BOOL operator<=(const CPerfTimer& Src); 00061 BOOL operator>=(const CPerfTimer& Src); 00062 // For time in seconds 00063 BOOL operator<(const double Secs); 00064 BOOL operator>(const double Secs); 00065 BOOL operator<=(const double Secs); 00066 BOOL operator>=(const double Secs); 00067 00068 virtual void Lock() const {;} // Override for thread safe operation 00069 virtual void Unlock() const {;} // Override for thread safe operation 00070 protected: 00071 void Init(BOOL bStart); 00072 void Copy(const CPerfTimer& Src); 00073 00074 private: 00075 __int64 m_Start; 00076 static __int64 m_Freq; // does not change while system is running 00077 static __int64 m_Adjust; // Adjustment time it takes to Start and Stop 00078 }; 00079 00080 class CPerfTimerT : public CPerfTimer 00081 { // You only need to use types of this class if a timer is going to be shared between threads 00082 public: 00083 CPerfTimerT(BOOL bStart = FALSE) 00084 { 00085 m_hMutex = CreateMutex(NULL,FALSE,""); 00086 Init(bStart); 00087 } 00088 00089 CPerfTimerT(const CPerfTimerT& Src) 00090 { 00091 m_hMutex = CreateMutex(NULL,FALSE,""); 00092 Copy(Src); 00093 } 00094 00095 CPerfTimerT(const CPerfTimer& Src) 00096 { 00097 m_hMutex = CreateMutex(NULL,FALSE,""); 00098 Copy(Src); 00099 } 00100 00101 virtual ~CPerfTimerT() 00102 { CloseHandle(m_hMutex); } 00103 00104 const CPerfTimerT& operator=(const CPerfTimerT& Src) // Assignment operator 00105 { 00106 Copy(Src); 00107 return *this; 00108 } 00109 00110 virtual void Lock() const { WaitForSingleObject(m_hMutex,10000); } 00111 virtual void Unlock() const { ReleaseMutex(m_hMutex); } 00112 private: 00113 HANDLE m_hMutex; 00114 }; 00115 00116 inline void CPerfTimer::Init(BOOL bStart) 00117 { 00118 if (!m_Freq) 00119 { // Initialization should only run once 00120 QueryPerformanceFrequency((LARGE_INTEGER *)&m_Freq); 00121 if (!m_Freq) 00122 m_Freq = 1; // Timer will be useless but will not cause divide by zero 00123 m_Start = 0; 00124 m_Adjust = 0; 00125 Start(); // Time a Stop 00126 Stop(); 00127 m_Adjust = m_Start; 00128 } 00129 // This is the only part that normally runs 00130 m_Start = 0; 00131 if (bStart) 00132 Start(); 00133 } 00134 00135 inline CPerfTimer::CPerfTimer(const CPerfTimer& Src) 00136 { 00137 Copy(Src); 00138 } 00139 00140 inline void CPerfTimer::Copy(const CPerfTimer& Src) 00141 { 00142 if (&Src == this) 00143 return; // avoid deadlock if someone tries to copy it to itself 00144 Src.Lock(); 00145 Lock(); 00146 m_Start = Src.m_Start; 00147 Unlock(); 00148 Src.Unlock(); 00149 } 00150 00151 inline void CPerfTimer::Start(BOOL bReset) 00152 { // Start from current value or optionally from 0 00153 __int64 i; 00154 QueryPerformanceCounter((LARGE_INTEGER *)&i); 00155 Lock(); 00156 if ((!bReset) && (m_Start < 0)) 00157 m_Start += i; // We are starting with an accumulated time 00158 else 00159 m_Start = i; // Starting from 0 00160 Unlock(); 00161 } 00162 00163 inline void CPerfTimer::Stop() 00164 { // Stop timing. Use Start afterwards to continue 00165 Lock(); 00166 if (m_Start <= 0) 00167 { 00168 Unlock(); 00169 return; // Was not running 00170 } 00171 __int64 i; 00172 QueryPerformanceCounter((LARGE_INTEGER *)&i); 00173 m_Start += -i; // Stopped timer keeps elapsed timer ticks as a negative 00174 if (m_Start < m_Adjust) // Do not overflow 00175 m_Start -= m_Adjust; // Adjust for time timer code takes to run 00176 else 00177 m_Start = 0; // Stop must have been called directly after Start 00178 Unlock(); 00179 } 00180 00181 inline BOOL CPerfTimer::IsRunning() 00182 { // Returns FALSE if stopped. 00183 Lock(); 00184 BOOL bRet = (m_Start > 0); // When < 0, holds elpased clicks 00185 Unlock(); 00186 return bRet; 00187 } 00188 inline const double CPerfTimer::Elapsed() 00189 { // Returns elapsed time in seconds 00190 CPerfTimer Result(*this); 00191 Result.Stop(); 00192 return (double)(-Result.m_Start)/(double)m_Freq; 00193 } 00194 00195 inline const double CPerfTimer::Elapsedms() 00196 { // Returns elapsed time in milliseconds 00197 CPerfTimer Result(*this); 00198 Result.Stop(); 00199 return (-Result.m_Start*1000.0)/(double)m_Freq; 00200 } 00201 00202 inline const double CPerfTimer::Elapsedus() 00203 { // Returns elapsed time in microseconds 00204 CPerfTimer Result(*this); 00205 Result.Stop(); 00206 return (-Result.m_Start * 1000000.0)/(double)m_Freq; 00207 } 00208 00209 00210 // Assignment operator 00211 inline const CPerfTimer& CPerfTimer::operator=(const CPerfTimer& Src) 00212 { 00213 Copy(Src); 00214 return *this; 00215 } 00216 00217 00218 // Math operators 00219 inline CPerfTimer CPerfTimer::operator+(const CPerfTimer& Src) const 00220 { 00221 CPerfTimer Result(*this); 00222 Result += Src; 00223 return Result; 00224 } 00225 00226 inline CPerfTimer CPerfTimer::operator-(const CPerfTimer& Src) const 00227 { 00228 CPerfTimer Result(*this); 00229 Result -= Src; 00230 return Result; 00231 } 00232 00233 inline const CPerfTimer& CPerfTimer::operator+=(const CPerfTimer& Src) 00234 { 00235 CPerfTimer SrcStop(Src); // Temp is necessary in case Src is not stopped 00236 SrcStop.Stop(); 00237 Lock(); 00238 m_Start += SrcStop.m_Start; 00239 Unlock(); 00240 return *this; 00241 } 00242 00243 inline const CPerfTimer& CPerfTimer::operator-=(const CPerfTimer& Src) 00244 { 00245 CPerfTimer SrcStop(Src); // Temp is necessary in case Src is not stopped 00246 SrcStop.Stop(); 00247 Lock(); 00248 m_Start -= SrcStop.m_Start; 00249 Unlock(); 00250 return *this; 00251 } 00252 00253 // For time in seconds 00254 inline CPerfTimer CPerfTimer::operator+(const double Secs) const 00255 { 00256 CPerfTimer Result(*this); 00257 Result += Secs; 00258 return Result; 00259 } 00260 00261 inline CPerfTimer CPerfTimer::operator-(const double Secs) const 00262 { 00263 CPerfTimer Result(*this); 00264 Result += Secs; 00265 return Result; 00266 } 00267 00268 inline const CPerfTimer& CPerfTimer::operator+=(const double Secs) 00269 { 00270 Lock(); 00271 m_Start -= (__int64)(Secs*(double)m_Freq); 00272 Unlock(); 00273 return *this; 00274 } 00275 00276 inline const CPerfTimer& CPerfTimer::operator-=(const double Secs) 00277 { 00278 Lock(); 00279 m_Start += (__int64)(Secs*(double)m_Freq); 00280 Unlock(); 00281 return *this; 00282 } 00283 00284 00285 00286 // Boolean comparison operators 00287 inline BOOL CPerfTimer::operator<(const CPerfTimer& Src) 00288 { 00289 BOOL bRet; 00290 CPerfTimer Temp(Src); 00291 Lock(); 00292 if (m_Start <= 0) 00293 { 00294 Temp.Stop(); 00295 bRet = (m_Start > Temp.m_Start); 00296 Unlock(); 00297 return bRet; 00298 } 00299 else 00300 if (Temp.m_Start > 0) 00301 { 00302 bRet = (m_Start < Temp.m_Start); 00303 Unlock(); 00304 return bRet; 00305 } 00306 else 00307 { 00308 Unlock(); 00309 CPerfTimer ThisStop(*this); 00310 ThisStop.Stop(); 00311 return (ThisStop.m_Start > Temp.m_Start); 00312 } 00313 } 00314 00315 inline BOOL CPerfTimer::operator>(const CPerfTimer& Src) 00316 { 00317 BOOL bRet; 00318 CPerfTimer Temp(Src); 00319 Lock(); 00320 if (m_Start <= 0) 00321 { 00322 Temp.Stop(); 00323 bRet = (m_Start < Temp.m_Start); 00324 Unlock(); 00325 return bRet; 00326 } 00327 else 00328 if (Temp.m_Start > 0) 00329 { 00330 bRet = (m_Start > Temp.m_Start); 00331 Unlock(); 00332 return bRet; 00333 } 00334 else 00335 { 00336 Unlock(); 00337 CPerfTimer ThisStop(*this); 00338 ThisStop.Stop(); 00339 return (ThisStop.m_Start < Temp.m_Start); 00340 } 00341 } 00342 00343 inline BOOL CPerfTimer::operator<=(const CPerfTimer& Src) 00344 { 00345 return !(*this > Src); 00346 } 00347 00348 inline BOOL CPerfTimer::operator>=(const CPerfTimer& Src) 00349 { 00350 return !(*this < Src); 00351 } 00352 00353 // For time in seconds 00354 inline BOOL CPerfTimer::operator<(const double Secs) 00355 { 00356 BOOL bRet; 00357 Lock(); 00358 if (m_Start <= 0) 00359 { 00360 bRet = (m_Start > (__int64)(-Secs*(double)m_Freq)); 00361 Unlock(); 00362 return bRet; 00363 } 00364 else 00365 { 00366 Unlock(); 00367 CPerfTimer ThisStop(*this); 00368 ThisStop.Stop(); 00369 return (ThisStop.m_Start > (__int64)(-Secs*(double)m_Freq)); 00370 } 00371 } 00372 00373 inline BOOL CPerfTimer::operator>(const double Secs) 00374 { 00375 BOOL bRet; 00376 Lock(); 00377 if (m_Start <= 0) 00378 { 00379 bRet = (m_Start < (__int64)(-Secs*(double)m_Freq)); 00380 Unlock(); 00381 return bRet; 00382 } 00383 else 00384 { 00385 Unlock(); 00386 CPerfTimer ThisStop(*this); 00387 ThisStop.Stop(); 00388 return (ThisStop.m_Start < (__int64)(-Secs*(double)m_Freq)); 00389 } 00390 } 00391 00392 inline BOOL CPerfTimer::operator<=(const double Secs) 00393 { 00394 return !(*this > Secs); 00395 } 00396 00397 inline BOOL CPerfTimer::operator>=(const double Secs) 00398 { 00399 return !(*this < Secs); 00400 } 00401 00402 00403 #endif //__PERFTIMER_H__