Mercurial > vba-clojure
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 wrapper2 // by Dean Wyant dwyant@mindspring.com4 /*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 a8 timer by calling Stop() and then you can call Start() to resume. Retrieve the9 elapsed time by calling an Elapsed..() function. Assignment, addition,10 subtraction and comparison are supported. There are a few information calls11 available also. All calls except Start and Stop can be performed on a timer12 without stopping it.14 */16 #ifndef __PERFTIMER_H__17 #define __PERFTIMER_H__19 class CPerfTimer20 {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 029 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 CPerfTimer36 const double Resolution(); // Returns timer resolution in seconds37 const double Resolutionms(); // Returns timer resolution in milliseconds38 const double Resolutionus(); // Returns timer resolution in microseconds40 const double Elapsed(); // Returns elapsed time in seconds41 const double Elapsedms(); // Returns elapsed time in milliseconds42 const double Elapsedus(); // Returns elapsed time in microseconds44 const CPerfTimer& operator=(const CPerfTimer& Src); // Assignment operator46 // Math operators47 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 seconds52 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 operators58 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 seconds63 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 operation69 virtual void Unlock() const {;} // Override for thread safe operation70 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 running77 static __int64 m_Adjust; // Adjustment time it takes to Start and Stop78 };80 class CPerfTimerT : public CPerfTimer81 { // You only need to use types of this class if a timer is going to be shared between threads82 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 operator105 {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 once120 QueryPerformanceFrequency((LARGE_INTEGER *)&m_Freq);121 if (!m_Freq)122 m_Freq = 1; // Timer will be useless but will not cause divide by zero123 m_Start = 0;124 m_Adjust = 0;125 Start(); // Time a Stop126 Stop();127 m_Adjust = m_Start;128 }129 // This is the only part that normally runs130 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 itself144 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 0153 __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 time158 else159 m_Start = i; // Starting from 0160 Unlock();161 }163 inline void CPerfTimer::Stop()164 { // Stop timing. Use Start afterwards to continue165 Lock();166 if (m_Start <= 0)167 {168 Unlock();169 return; // Was not running170 }171 __int64 i;172 QueryPerformanceCounter((LARGE_INTEGER *)&i);173 m_Start += -i; // Stopped timer keeps elapsed timer ticks as a negative174 if (m_Start < m_Adjust) // Do not overflow175 m_Start -= m_Adjust; // Adjust for time timer code takes to run176 else177 m_Start = 0; // Stop must have been called directly after Start178 Unlock();179 }181 inline BOOL CPerfTimer::IsRunning()182 { // Returns FALSE if stopped.183 Lock();184 BOOL bRet = (m_Start > 0); // When < 0, holds elpased clicks185 Unlock();186 return bRet;187 }188 inline const double CPerfTimer::Elapsed()189 { // Returns elapsed time in seconds190 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 milliseconds197 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 microseconds204 CPerfTimer Result(*this);206 return (-Result.m_Start * 1000000.0)/(double)m_Freq;207 }210 // Assignment operator211 inline const CPerfTimer& CPerfTimer::operator=(const CPerfTimer& Src)212 {213 Copy(Src);214 return *this;215 }218 // Math operators219 inline CPerfTimer CPerfTimer::operator+(const CPerfTimer& Src) const220 {221 CPerfTimer Result(*this);222 Result += Src;223 return Result;224 }226 inline CPerfTimer CPerfTimer::operator-(const CPerfTimer& Src) const227 {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 stopped236 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 stopped246 SrcStop.Stop();247 Lock();248 m_Start -= SrcStop.m_Start;249 Unlock();250 return *this;251 }253 // For time in seconds254 inline CPerfTimer CPerfTimer::operator+(const double Secs) const255 {256 CPerfTimer Result(*this);257 Result += Secs;258 return Result;259 }261 inline CPerfTimer CPerfTimer::operator-(const double Secs) const262 {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 operators287 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 else300 if (Temp.m_Start > 0)301 {302 bRet = (m_Start < Temp.m_Start);303 Unlock();304 return bRet;305 }306 else307 {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 else328 if (Temp.m_Start > 0)329 {330 bRet = (m_Start > Temp.m_Start);331 Unlock();332 return bRet;333 }334 else335 {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 seconds354 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 else365 {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 else384 {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__