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