QueryPerformanceCounter() provides higher resolution and precision for
measuring time under MSW, even though it suffers from some problems in older
Windows versions.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69834
c3d73ce0-8a6f-49c7-b76d-
6d57e0e08775
wxLogMessage("And calling it twice took $ldms in all", sw.Time());
@endcode
wxLogMessage("And calling it twice took $ldms in all", sw.Time());
@endcode
+ Since wxWidgets 2.9.3 this class uses @c ::QueryPerformanceCounter()
+ function under MSW to measure the elapsed time. It provides higher
+ precision than the usual timer functions but can suffer from bugs in its
+ implementation in some Windows XP versions. If you encounter such problems,
+ installing a Microsoft hot fix from http://support.microsoft.com/?id=896256
+ could be necessary.
+
@library{wxbase}
@category{misc}
@library{wxbase}
@category{misc}
+#ifdef __WXMSW__
+
+namespace
+{
+
+struct PerfCounter
+{
+ PerfCounter()
+ {
+ init = false;
+ }
+
+ bool CanBeUsed() const
+ {
+ return freq.QuadPart != 0;
+ }
+
+ wxCriticalSection cs;
+ LARGE_INTEGER freq;
+ bool init;
+} gs_perfCounter;
+
+} // anonymous namespace
+
+#endif // __WXMSW__
+
void wxStopWatch::Start(long t)
{
void wxStopWatch::Start(long t)
{
-#if 0
-// __WXMSW__
- LARGE_INTEGER frequency_li;
- ::QueryPerformanceFrequency( &frequency_li );
- m_frequency = frequency_li.QuadPart;
- if (m_frequency == 0)
+#ifdef __WXMSW__
+ if ( !gs_perfCounter.init )
- m_t0 = wxGetLocalTimeMillis() - t;
+ wxCriticalSectionLocker lock(gs_perfCounter.cs);
+ ::QueryPerformanceFrequency(&gs_perfCounter.freq);
+ gs_perfCounter.init = true;
+
+ LARGE_INTEGER counter;
+ if ( gs_perfCounter.CanBeUsed() && ::QueryPerformanceCounter(&counter) )
- LARGE_INTEGER counter_li;
- ::QueryPerformanceCounter( &counter_li );
- wxLongLong counter = counter_li.QuadPart;
- m_t0 = (counter * 10000 / m_frequency) - t*10;
+ m_t0 = counter.QuadPart - t*gs_perfCounter.freq.QuadPart/1000;
-#else
- m_t0 = wxGetLocalTimeMillis() - t;
-#endif
+ else // Fall back to the generic code below.
+#endif // __WXMSW__
+ {
+ m_t0 = wxGetLocalTimeMillis() - t;
+ }
+
m_pause = 0;
m_pauseCount = 0;
}
long wxStopWatch::GetElapsedTime() const
{
m_pause = 0;
m_pauseCount = 0;
}
long wxStopWatch::GetElapsedTime() const
{
-#if 0
-//__WXMSW__
- if (m_frequency == 0)
+#ifdef __WXMSW__
+ LARGE_INTEGER counter;
+ if ( gs_perfCounter.CanBeUsed() && ::QueryPerformanceCounter(&counter) )
- return (wxGetLocalTimeMillis() - m_t0).GetLo();
- }
- else
- {
- LARGE_INTEGER counter_li;
- ::QueryPerformanceCounter( &counter_li );
- wxLongLong counter = counter_li.QuadPart;
- wxLongLong res = (counter * 10000 / m_frequency) - m_t0;
- return res.GetLo() / 10;
+ wxLongLong delta(counter.QuadPart);
+ delta -= m_t0;
+
+ return ((delta*1000)/gs_perfCounter.freq.QuadPart).GetLo();
-#else
- return (wxGetLocalTimeMillis() - m_t0).GetLo();
+ return (wxGetLocalTimeMillis() - m_t0).GetLo();
}
long wxStopWatch::Time() const
}
long wxStopWatch::Time() const