]> git.saurik.com Git - wxWidgets.git/blame - src/common/stopwatch.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / stopwatch.cpp
CommitLineData
e2478fde 1///////////////////////////////////////////////////////////////////////////////
57bd4c60 2// Name: src/common/stopwatch.cpp
e2478fde
VZ
3// Purpose: wxStopWatch and other non-GUI stuff from wx/timer.h
4// Author:
5// Original version by Julian Smart
6// Vadim Zeitlin got rid of all ifdefs (11.12.99)
7// Sylvain Bougnoux added wxStopWatch class
8// Guillermo Rodriguez <guille@iies.es> rewrote from scratch (Dic/99)
9// Modified by:
10// Created: 20.06.2003 (extracted from common/timercmn.cpp)
11// RCS-ID: $Id$
77ffb593 12// Copyright: (c) 1998-2003 wxWidgets Team
526954c5 13// Licence: wxWindows licence
e2478fde
VZ
14///////////////////////////////////////////////////////////////////////////////
15
16// ============================================================================
17// declarations
18// ============================================================================
19
20// ----------------------------------------------------------------------------
21// headers
22// ----------------------------------------------------------------------------
23
24// for compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
bb90a3e6
WS
31#include "wx/stopwatch.h"
32
173a5ddc
VZ
33#if wxUSE_STOPWATCH
34
e2478fde 35#ifndef WX_PRECOMP
d98a58c5 36 #ifdef __WINDOWS__
57bd4c60
WS
37 #include "wx/msw/wrapwin.h"
38 #endif
8df6de97 39 #include "wx/log.h"
0c717dd1 40 #include "wx/thread.h"
e2478fde
VZ
41#endif //WX_PRECOMP
42
e2478fde
VZ
43// ============================================================================
44// implementation
45// ============================================================================
46
47// ----------------------------------------------------------------------------
48// wxStopWatch
49// ----------------------------------------------------------------------------
50
54647bb7
VZ
51namespace
52{
53
d98a58c5 54#ifdef __WINDOWS__
b0ec0023 55
54647bb7
VZ
56struct PerfCounter
57{
58 PerfCounter()
59 {
60 init = false;
61 }
62
63 bool CanBeUsed() const
64 {
65 return freq.QuadPart != 0;
66 }
67
0c717dd1 68 wxCRIT_SECT_DECLARE_MEMBER(cs);
54647bb7
VZ
69 LARGE_INTEGER freq;
70 bool init;
71} gs_perfCounter;
72
d98a58c5 73#endif // __WINDOWS__
54647bb7 74
b0ec0023 75const int MILLISECONDS_PER_SECOND = 1000;
a43503cb 76const int MICROSECONDS_PER_MILLISECOND = 1000;
b0ec0023
VZ
77const int MICROSECONDS_PER_SECOND = 1000*1000;
78
79} // anonymous namespace
80
81void wxStopWatch::DoStart()
e2478fde 82{
d98a58c5 83#ifdef __WINDOWS__
54647bb7 84 if ( !gs_perfCounter.init )
2555c77a 85 {
0c717dd1 86 wxCRIT_SECT_LOCKER(lock, gs_perfCounter.cs);
54647bb7 87 ::QueryPerformanceFrequency(&gs_perfCounter.freq);
b0ec0023
VZ
88
89 // Just a sanity check: it's not supposed to happen but verify that
90 // ::QueryPerformanceCounter() succeeds so that we can really use it.
91 LARGE_INTEGER counter;
92 if ( !::QueryPerformanceCounter(&counter) )
93 {
94 wxLogDebug("QueryPerformanceCounter() unexpected failed (%s), "
95 "will not use it.", wxSysErrorMsg());
96
97 gs_perfCounter.freq.QuadPart = 0;
98 }
99
54647bb7 100 gs_perfCounter.init = true;
2555c77a 101 }
d98a58c5 102#endif // __WINDOWS__
54647bb7 103
b0ec0023
VZ
104 m_t0 = GetCurrentClockValue();
105}
106
107wxLongLong wxStopWatch::GetClockFreq() const
108{
d98a58c5 109#ifdef __WINDOWS__
b0ec0023
VZ
110 // Under MSW we use the high resolution performance counter timer which has
111 // its own frequency (usually related to the CPU clock speed).
112 if ( gs_perfCounter.CanBeUsed() )
113 return gs_perfCounter.freq.QuadPart;
d98a58c5 114#endif // __WINDOWS__
54647bb7 115
796e54ef
VZ
116#ifdef HAVE_GETTIMEOFDAY
117 // With gettimeofday() we can have nominally microsecond precision and
118 // while this is not the case in practice, it's still better than
119 // millisecond.
120 return MICROSECONDS_PER_SECOND;
121#else // !HAVE_GETTIMEOFDAY
b0ec0023
VZ
122 // Currently milliseconds are used everywhere else.
123 return MILLISECONDS_PER_SECOND;
796e54ef 124#endif // HAVE_GETTIMEOFDAY/!HAVE_GETTIMEOFDAY
e2478fde
VZ
125}
126
b0ec0023
VZ
127void wxStopWatch::Start(long t0)
128{
17d72a48
VZ
129 // Calling Start() makes the stop watch run however many times it was
130 // paused before.
131 m_pauseCount = 0;
132
b0ec0023
VZ
133 DoStart();
134
135 m_t0 -= (wxLongLong(t0)*GetClockFreq())/MILLISECONDS_PER_SECOND;
136}
137
138wxLongLong wxStopWatch::GetCurrentClockValue() const
e2478fde 139{
d98a58c5 140#ifdef __WINDOWS__
b0ec0023 141 if ( gs_perfCounter.CanBeUsed() )
2555c77a 142 {
b0ec0023
VZ
143 LARGE_INTEGER counter;
144 ::QueryPerformanceCounter(&counter);
145 return counter.QuadPart;
2555c77a 146 }
d98a58c5 147#endif // __WINDOWS__
b0ec0023 148
796e54ef
VZ
149#ifdef HAVE_GETTIMEOFDAY
150 return wxGetUTCTimeUSec();
151#else // !HAVE_GETTIMEOFDAY
e1645882 152 return wxGetUTCTimeMillis();
796e54ef 153#endif // HAVE_GETTIMEOFDAY/!HAVE_GETTIMEOFDAY
e2478fde
VZ
154}
155
b0ec0023 156wxLongLong wxStopWatch::TimeInMicro() const
e2478fde 157{
b0ec0023
VZ
158 const wxLongLong elapsed(m_pauseCount ? m_elapsedBeforePause
159 : GetCurrentClockValue() - m_t0);
160
161 return (elapsed*MICROSECONDS_PER_SECOND)/GetClockFreq();
e2478fde
VZ
162}
163
164#endif // wxUSE_STOPWATCH
165
166// ----------------------------------------------------------------------------
167// old timer functions superceded by wxStopWatch
168// ----------------------------------------------------------------------------
169
170#if wxUSE_LONGLONG
171
172static wxLongLong wxStartTime = 0l;
173
174// starts the global timer
175void wxStartTimer()
176{
e1645882 177 wxStartTime = wxGetUTCTimeMillis();
e2478fde
VZ
178}
179
180// Returns elapsed time in milliseconds
181long wxGetElapsedTime(bool resetTimer)
182{
183 wxLongLong oldTime = wxStartTime;
e1645882 184 wxLongLong newTime = wxGetUTCTimeMillis();
e2478fde
VZ
185
186 if ( resetTimer )
187 wxStartTime = newTime;
188
189 return (newTime - oldTime).GetLo();
190}
191
192#endif // wxUSE_LONGLONG