Filter Library Camera Interface Physics

PerfTimer.h

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__

Camera Filter Library documentation © 2004-2007 by Leiden Probe Microscopy