1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_canvas.hxx"
26
27 #include "osl/time.h"
28 #include "osl/diagnose.h"
29 #include "canvas/elapsedtime.hxx"
30
31 #if defined(WNT)
32
33 #if defined _MSC_VER
34 #pragma warning(push,1)
35 #endif
36
37 // TEMP!!!
38 // Awaiting corresponding functionality in OSL
39 //
40 #define WIN32_LEAN_AND_MEAN
41 #include <windows.h>
42 #include <winbase.h>
43 #include <mmsystem.h>
44 #endif
45
46 #if defined _MSC_VER
47 #pragma warning(pop)
48 #endif
49
50 #include <algorithm>
51 #include <limits>
52
53 namespace canvas {
54 namespace tools {
55
56
57 #if defined(WNT)
58 // TODO(Q2): is 0 okay for the failure case here?
getSystemTime()59 double ElapsedTime::getSystemTime()
60 {
61 // TEMP!!!
62 // Awaiting corresponding functionality in OSL
63 //
64
65 // is there a performance counter available?
66 static bool bTimeSetupDone( false );
67 static bool bPerfTimerAvailable( false );
68 static LONGLONG nPerfCountFreq;
69
70 // TODO(F1): This _might_ cause problems, as it prevents correct
71 // time handling for very long lifetimes of this class's
72 // surrounding component in memory. When the difference between
73 // current sys time and nInitialCount exceeds IEEE double's
74 // mantissa, time will start to run jerky.
75 static LONGLONG nInitialCount;
76
77 if( !bTimeSetupDone )
78 {
79 if( QueryPerformanceFrequency(
80 reinterpret_cast<LARGE_INTEGER *>(&nPerfCountFreq) ) )
81 {
82 // read initial time:
83 QueryPerformanceCounter(
84 reinterpret_cast<LARGE_INTEGER *>(&nInitialCount) );
85 bPerfTimerAvailable = true;
86 }
87 bTimeSetupDone = true;
88 }
89
90 if( bPerfTimerAvailable )
91 {
92 LONGLONG nCurrCount;
93 QueryPerformanceCounter(
94 reinterpret_cast<LARGE_INTEGER *>(&nCurrCount) );
95 nCurrCount -= nInitialCount;
96 return double(nCurrCount) / nPerfCountFreq;
97 }
98 else
99 {
100 LONGLONG nCurrTime = timeGetTime();
101 return double(nCurrTime) / 1000.0;
102 }
103 }
104
105 #else // ! WNT
106
107 // TODO(Q2): is 0 okay for the failure case here?
108 double ElapsedTime::getSystemTime()
109 {
110 TimeValue aTimeVal;
111 if( osl_getSystemTime( &aTimeVal ) )
112 return ((aTimeVal.Nanosec * 10e-10) + aTimeVal.Seconds);
113 else
114 return 0.0;
115 }
116
117 #endif
118
ElapsedTime()119 ElapsedTime::ElapsedTime()
120 : m_pTimeBase(),
121 m_fLastQueriedTime( 0.0 ),
122 m_fStartTime( getSystemTime() ),
123 m_fFrozenTime( 0.0 ),
124 m_bInPauseMode( false ),
125 m_bInHoldMode( false )
126 {
127 }
128
ElapsedTime(boost::shared_ptr<ElapsedTime> const & pTimeBase)129 ElapsedTime::ElapsedTime(
130 boost::shared_ptr<ElapsedTime> const & pTimeBase )
131 : m_pTimeBase( pTimeBase ),
132 m_fLastQueriedTime( 0.0 ),
133 m_fStartTime( getCurrentTime() ),
134 m_fFrozenTime( 0.0 ),
135 m_bInPauseMode( false ),
136 m_bInHoldMode( false )
137 {
138 }
139
getTimeBase() const140 boost::shared_ptr<ElapsedTime> const & ElapsedTime::getTimeBase() const
141 {
142 return m_pTimeBase;
143 }
144
reset()145 void ElapsedTime::reset()
146 {
147 m_fLastQueriedTime = 0.0;
148 m_fStartTime = getCurrentTime();
149 m_fFrozenTime = 0.0;
150 m_bInPauseMode = false;
151 m_bInHoldMode = false;
152 }
153
adjustTimer(double fOffset,bool)154 void ElapsedTime::adjustTimer( double fOffset, bool /*bLimitToLastQueriedTime*/ )
155 {
156 // to make getElapsedTime() become _larger_, have to reduce
157 // m_fStartTime.
158 m_fStartTime -= fOffset;
159
160 // also adjust frozen time, this method must _always_ affect the
161 // value returned by getElapsedTime()!
162 if (m_bInHoldMode || m_bInPauseMode)
163 m_fFrozenTime += fOffset;
164 }
165
getCurrentTime() const166 double ElapsedTime::getCurrentTime() const
167 {
168 return m_pTimeBase.get() == 0
169 ? getSystemTime() : m_pTimeBase->getElapsedTimeImpl();
170 }
171
getElapsedTime() const172 double ElapsedTime::getElapsedTime() const
173 {
174 m_fLastQueriedTime = getElapsedTimeImpl();
175 return m_fLastQueriedTime;
176 }
177
getElapsedTimeImpl() const178 double ElapsedTime::getElapsedTimeImpl() const
179 {
180 if (m_bInHoldMode || m_bInPauseMode)
181 return m_fFrozenTime;
182
183 return getCurrentTime() - m_fStartTime;
184 }
185
pauseTimer()186 void ElapsedTime::pauseTimer()
187 {
188 m_fFrozenTime = getElapsedTimeImpl();
189 m_bInPauseMode = true;
190 }
191
continueTimer()192 void ElapsedTime::continueTimer()
193 {
194 m_bInPauseMode = false;
195
196 // stop pausing, time runs again. Note that
197 // getElapsedTimeImpl() honors hold mode, i.e. a
198 // continueTimer() in hold mode will preserve the latter
199 const double fPauseDuration( getElapsedTimeImpl() - m_fFrozenTime );
200
201 // adjust start time, such that subsequent getElapsedTime() calls
202 // will virtually start from m_fFrozenTime.
203 m_fStartTime += fPauseDuration;
204 }
205
holdTimer()206 void ElapsedTime::holdTimer()
207 {
208 // when called during hold mode (e.g. more than once per time
209 // object), the original hold time will be maintained.
210 m_fFrozenTime = getElapsedTimeImpl();
211 m_bInHoldMode = true;
212 }
213
releaseTimer()214 void ElapsedTime::releaseTimer()
215 {
216 m_bInHoldMode = false;
217 }
218
219 } // namespace tools
220 } // namespace canvas
221