]> git.saurik.com Git - wxWidgets.git/blob - src/common/stopwatch.cpp
Dramatically optimise inserting many items in wxGenericListCtrl.
[wxWidgets.git] / src / common / stopwatch.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/stopwatch.cpp
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$
12 // Copyright: (c) 1998-2003 wxWidgets Team
13 // Licence: wxWindows licence
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
31 #include "wx/stopwatch.h"
32
33 #if wxUSE_STOPWATCH
34
35 #ifndef WX_PRECOMP
36 #ifdef __WXMSW__
37 #include "wx/msw/wrapwin.h"
38 #endif
39 #include "wx/log.h"
40 #include "wx/thread.h"
41 #endif //WX_PRECOMP
42
43 // ============================================================================
44 // implementation
45 // ============================================================================
46
47 // ----------------------------------------------------------------------------
48 // wxStopWatch
49 // ----------------------------------------------------------------------------
50
51 namespace
52 {
53
54 #ifdef __WXMSW__
55
56 struct PerfCounter
57 {
58 PerfCounter()
59 {
60 init = false;
61 }
62
63 bool CanBeUsed() const
64 {
65 return freq.QuadPart != 0;
66 }
67
68 wxCRIT_SECT_DECLARE_MEMBER(cs);
69 LARGE_INTEGER freq;
70 bool init;
71 } gs_perfCounter;
72
73 #endif // __WXMSW__
74
75 const int MILLISECONDS_PER_SECOND = 1000;
76 const int MICROSECONDS_PER_MILLISECOND = 1000;
77 const int MICROSECONDS_PER_SECOND = 1000*1000;
78
79 } // anonymous namespace
80
81 void wxStopWatch::DoStart()
82 {
83 #ifdef __WXMSW__
84 if ( !gs_perfCounter.init )
85 {
86 wxCRIT_SECT_LOCKER(lock, gs_perfCounter.cs);
87 ::QueryPerformanceFrequency(&gs_perfCounter.freq);
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
100 gs_perfCounter.init = true;
101 }
102 #endif // __WXMSW__
103
104 m_t0 = GetCurrentClockValue();
105 }
106
107 wxLongLong wxStopWatch::GetClockFreq() const
108 {
109 #ifdef __WXMSW__
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;
114 #endif // __WXMSW__
115
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
122 // Currently milliseconds are used everywhere else.
123 return MILLISECONDS_PER_SECOND;
124 #endif // HAVE_GETTIMEOFDAY/!HAVE_GETTIMEOFDAY
125 }
126
127 void wxStopWatch::Start(long t0)
128 {
129 // Calling Start() makes the stop watch run however many times it was
130 // paused before.
131 m_pauseCount = 0;
132
133 DoStart();
134
135 m_t0 -= (wxLongLong(t0)*GetClockFreq())/MILLISECONDS_PER_SECOND;
136 }
137
138 wxLongLong wxStopWatch::GetCurrentClockValue() const
139 {
140 #ifdef __WXMSW__
141 if ( gs_perfCounter.CanBeUsed() )
142 {
143 LARGE_INTEGER counter;
144 ::QueryPerformanceCounter(&counter);
145 return counter.QuadPart;
146 }
147 #endif // __WXMSW__
148
149 #ifdef HAVE_GETTIMEOFDAY
150 return wxGetUTCTimeUSec();
151 #else // !HAVE_GETTIMEOFDAY
152 return wxGetUTCTimeMillis();
153 #endif // HAVE_GETTIMEOFDAY/!HAVE_GETTIMEOFDAY
154 }
155
156 wxLongLong wxStopWatch::TimeInMicro() const
157 {
158 const wxLongLong elapsed(m_pauseCount ? m_elapsedBeforePause
159 : GetCurrentClockValue() - m_t0);
160
161 return (elapsed*MICROSECONDS_PER_SECOND)/GetClockFreq();
162 }
163
164 #endif // wxUSE_STOPWATCH
165
166 // ----------------------------------------------------------------------------
167 // old timer functions superceded by wxStopWatch
168 // ----------------------------------------------------------------------------
169
170 #if wxUSE_LONGLONG
171
172 static wxLongLong wxStartTime = 0l;
173
174 // starts the global timer
175 void wxStartTimer()
176 {
177 wxStartTime = wxGetUTCTimeMillis();
178 }
179
180 // Returns elapsed time in milliseconds
181 long wxGetElapsedTime(bool resetTimer)
182 {
183 wxLongLong oldTime = wxStartTime;
184 wxLongLong newTime = wxGetUTCTimeMillis();
185
186 if ( resetTimer )
187 wxStartTime = newTime;
188
189 return (newTime - oldTime).GetLo();
190 }
191
192 #endif // wxUSE_LONGLONG