xref: /AOO41X/main/canvas/source/tools/elapsedtime.cxx (revision 25ea7f451e822ec0589487f23a9b6cc31f03fcc3)
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