Line data Source code
1 :
2 : /* Copyright (c) 2010-2014, Stefan Eilemann <eile@eyescale.ch>
3 : *
4 : * This library is free software; you can redistribute it and/or modify it under
5 : * the terms of the GNU Lesser General Public License version 2.1 as published
6 : * by the Free Software Foundation.
7 : *
8 : * This library is distributed in the hope that it will be useful, but WITHOUT
9 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 : * details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this library; if not, write to the Free Software Foundation, Inc.,
15 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 : */
17 :
18 :
19 : #include "clock.h"
20 :
21 : #include "os.h"
22 :
23 : #include <lunchbox/os.h>
24 : #ifdef __APPLE__
25 : // http://developer.apple.com/qa/qa2004/qa1398.html
26 : # include <mach/mach_time.h>
27 : #endif
28 : #ifndef _WIN32
29 : # include <time.h>
30 : #endif
31 :
32 : namespace lunchbox
33 : {
34 : namespace detail
35 : {
36 : class Clock
37 : {
38 : public:
39 : #ifdef __APPLE__
40 : uint64_t start;
41 : mach_timebase_info_data_t timebaseInfo;
42 : #elif defined (_WIN32)
43 : LARGE_INTEGER start;
44 : LARGE_INTEGER frequency;
45 : #else
46 : struct timespec start;
47 : #endif
48 : };
49 : }
50 :
51 206 : Clock::Clock()
52 206 : : _impl( new detail::Clock )
53 : {
54 206 : reset();
55 : #ifdef __APPLE__
56 : mach_timebase_info( &_impl->timebaseInfo );
57 : #elif defined (_WIN32)
58 : QueryPerformanceFrequency( &_impl->frequency );
59 : #endif
60 206 : }
61 :
62 1 : Clock::Clock( const Clock& from )
63 1 : : _impl( new detail::Clock( *from._impl ))
64 1 : {}
65 :
66 0 : Clock & Clock::operator= ( const Clock& ref )
67 : {
68 0 : *_impl = *ref._impl;
69 0 : return *this;
70 : }
71 :
72 207 : Clock::~Clock()
73 : {
74 207 : delete _impl;
75 207 : }
76 :
77 594 : void Clock::reset()
78 : {
79 : #ifdef __APPLE__
80 : _impl->start = mach_absolute_time();
81 : #elif defined (_WIN32)
82 : QueryPerformanceCounter( &_impl->start );
83 : #else
84 594 : clock_gettime( CLOCK_REALTIME, &_impl->start );
85 : #endif
86 594 : }
87 :
88 0 : void Clock::set( const int64_t time )
89 : {
90 0 : reset();
91 : #ifdef __APPLE__
92 : _impl->start -= static_cast< uint64_t >(
93 : time * _impl->timebaseInfo.denom / _impl->timebaseInfo.numer *
94 : 1000000 );
95 : #elif defined (_WIN32)
96 : _impl->start.QuadPart -= static_cast<long long>(
97 : time * _impl->frequency.QuadPart / 1000 );
98 : #else
99 0 : const int sec = static_cast< int >( time / 1000 ) + 1;
100 0 : _impl->start.tv_sec -= sec;
101 : _impl->start.tv_nsec -= static_cast<int>(
102 0 : (time - sec * 1000) * 1000000 );
103 0 : if( _impl->start.tv_nsec > 1000000000 )
104 : {
105 0 : _impl->start.tv_sec += 1;
106 0 : _impl->start.tv_nsec -= 1000000000;
107 : }
108 : #endif
109 0 : }
110 :
111 2316 : float Clock::getTimef() const
112 : {
113 : #ifdef __APPLE__
114 : const int64_t elapsed = mach_absolute_time() - _impl->start;
115 : return ( elapsed * _impl->timebaseInfo.numer / _impl->timebaseInfo.denom /
116 : 1000000.f );
117 : #elif defined (_WIN32)
118 : LARGE_INTEGER now;
119 : QueryPerformanceCounter( &now );
120 : return 1000.0f * (now.QuadPart - _impl->start.QuadPart) /
121 : _impl->frequency.QuadPart;
122 : #else
123 : struct timespec now;
124 2316 : clock_gettime( CLOCK_REALTIME, &now );
125 2314 : return ( 1000.0f * (now.tv_sec - _impl->start.tv_sec) +
126 2314 : 0.000001f * (now.tv_nsec - _impl->start.tv_nsec));
127 : #endif
128 : }
129 :
130 1 : float Clock::resetTimef()
131 : {
132 : #ifdef __APPLE__
133 : const uint64_t now = mach_absolute_time();
134 : const int64_t elapsed = now - _impl->start;
135 : const float time = elapsed * _impl->timebaseInfo.numer /
136 : _impl->timebaseInfo.denom / 1000000.f;
137 : #elif defined (_WIN32)
138 : LARGE_INTEGER now;
139 : QueryPerformanceCounter( &now );
140 : const float time = 1000.0f * (now.QuadPart - _impl->start.QuadPart) /
141 : _impl->frequency.QuadPart;
142 : #else
143 : struct timespec now;
144 1 : clock_gettime( CLOCK_REALTIME, &now );
145 1 : const float time = ( 1000.0f * (now.tv_sec - _impl->start.tv_sec) +
146 1 : 0.000001f * (now.tv_nsec - _impl->start.tv_nsec));
147 : #endif
148 1 : _impl->start = now;
149 1 : return time;
150 : }
151 :
152 675066 : int64_t Clock::getTime64() const
153 : {
154 : #ifdef __APPLE__
155 : const int64_t elapsed = mach_absolute_time() - _impl->start;
156 : return ( elapsed * _impl->timebaseInfo.numer /
157 : _impl->timebaseInfo.denom + 500000 ) / 1000000;
158 : #elif defined (_WIN32)
159 : LARGE_INTEGER now;
160 : QueryPerformanceCounter( &now );
161 : return ( 1000 * (now.QuadPart-_impl->start.QuadPart) +
162 : (_impl->frequency.QuadPart>>1) ) / _impl->frequency.QuadPart;
163 : #else
164 : struct timespec now;
165 675066 : clock_gettime( CLOCK_REALTIME, &now );
166 1382088 : return ( 1000 * (now.tv_sec - _impl->start.tv_sec) +
167 1382088 : int64_t( 0.000001f * (now.tv_nsec - _impl->start.tv_nsec+500000)));
168 : #endif
169 : }
170 :
171 27 : double Clock::getTimed() const
172 : {
173 : #ifdef __APPLE__
174 : const int64_t elapsed = mach_absolute_time() - _impl->start;
175 : return ( elapsed * _impl->timebaseInfo.numer / _impl->timebaseInfo.denom /
176 : 1000000. );
177 : #elif defined (_WIN32)
178 : LARGE_INTEGER now;
179 : QueryPerformanceCounter( &now );
180 : return 1000.0 * (now.QuadPart - _impl->start.QuadPart) /
181 : _impl->frequency.QuadPart;
182 : #else
183 : struct timespec now;
184 27 : clock_gettime( CLOCK_REALTIME, &now );
185 27 : return ( 1000.0 * (now.tv_sec - _impl->start.tv_sec) +
186 27 : 0.000001 * (now.tv_nsec - _impl->start.tv_nsec));
187 : #endif
188 : }
189 :
190 0 : float Clock::getMilliSecondsf() const
191 : {
192 : #if defined (__APPLE__) || defined (_WIN32)
193 : double time = getTimed();
194 : return static_cast<float>
195 : (time - static_cast<unsigned>(time/1000.) * 1000);
196 : #else
197 : struct timespec now;
198 0 : clock_gettime( CLOCK_REALTIME, &now );
199 :
200 0 : if( now.tv_nsec < _impl->start.tv_nsec )
201 0 : return ( 1000.f + 0.000001f*(now.tv_nsec - _impl->start.tv_nsec));
202 :
203 0 : return ( 0.000001f * ( now.tv_nsec - _impl->start.tv_nsec ));
204 : #endif
205 : }
206 :
207 : }
|