Use ::QueryPerformanceCounter() for wxStopWatch implementation in wxMSW.

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
This commit is contained in:
Vadim Zeitlin 2011-11-27 19:50:08 +00:00
parent c439998525
commit 54647bb750
2 changed files with 57 additions and 30 deletions

View File

@ -25,6 +25,13 @@
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}

View File

@ -95,50 +95,70 @@
#if wxUSE_STOPWATCH
#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)
{
#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 )
{
wxCriticalSectionLocker lock(gs_perfCounter.cs);
::QueryPerformanceFrequency(&gs_perfCounter.freq);
gs_perfCounter.init = true;
}
LARGE_INTEGER counter;
if ( gs_perfCounter.CanBeUsed() && ::QueryPerformanceCounter(&counter) )
{
m_t0 = counter.QuadPart - t*gs_perfCounter.freq.QuadPart/1000;
}
else // Fall back to the generic code below.
#endif // __WXMSW__
{
m_t0 = wxGetLocalTimeMillis() - t;
}
else
{
LARGE_INTEGER counter_li;
::QueryPerformanceCounter( &counter_li );
wxLongLong counter = counter_li.QuadPart;
m_t0 = (counter * 10000 / m_frequency) - t*10;
}
#else
m_t0 = wxGetLocalTimeMillis() - t;
#endif
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();
wxLongLong delta(counter.QuadPart);
delta -= m_t0;
return ((delta*1000)/gs_perfCounter.freq.QuadPart).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;
}
#else
return (wxGetLocalTimeMillis() - m_t0).GetLo();
#endif
return (wxGetLocalTimeMillis() - m_t0).GetLo();
}
long wxStopWatch::Time() const