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 : #include "clock.h"
19 :
20 : #include "os.h"
21 :
22 : #include <lunchbox/os.h>
23 : #ifdef __APPLE__
24 : // http://developer.apple.com/qa/qa2004/qa1398.html
25 : #include <mach/mach_time.h>
26 : #endif
27 : #ifndef _WIN32
28 : #include <time.h>
29 : #endif
30 :
31 : namespace lunchbox
32 : {
33 : namespace detail
34 : {
35 : class Clock
36 : {
37 : public:
38 : #ifdef __APPLE__
39 : uint64_t start;
40 : mach_timebase_info_data_t timebaseInfo;
41 : #elif defined(_WIN32)
42 : LARGE_INTEGER start;
43 : LARGE_INTEGER frequency;
44 : #else
45 : struct timespec start;
46 : #endif
47 : };
48 : }
49 :
50 38 : Clock::Clock()
51 38 : : _impl(new detail::Clock)
52 : {
53 38 : reset();
54 : #ifdef __APPLE__
55 : mach_timebase_info(&_impl->timebaseInfo);
56 : #elif defined(_WIN32)
57 : QueryPerformanceFrequency(&_impl->frequency);
58 : #endif
59 38 : }
60 :
61 1 : Clock::Clock(const Clock& from)
62 1 : : _impl(new detail::Clock(*from._impl))
63 : {
64 1 : }
65 :
66 0 : Clock& Clock::operator=(const Clock& ref)
67 : {
68 0 : *_impl = *ref._impl;
69 0 : return *this;
70 : }
71 :
72 78 : Clock::~Clock()
73 : {
74 39 : delete _impl;
75 39 : }
76 :
77 42 : void Clock::reset()
78 : {
79 : #ifdef __APPLE__
80 : _impl->start = mach_absolute_time();
81 : #elif defined(_WIN32)
82 : QueryPerformanceCounter(&_impl->start);
83 : #else
84 42 : clock_gettime(CLOCK_REALTIME, &_impl->start);
85 : #endif
86 42 : }
87 :
88 0 : void Clock::set(const int64_t time)
89 : {
90 0 : reset();
91 : #ifdef __APPLE__
92 : _impl->start -= static_cast<uint64_t>(time * _impl->timebaseInfo.denom /
93 : _impl->timebaseInfo.numer * 1000000);
94 : #elif defined(_WIN32)
95 : _impl->start.QuadPart -=
96 : static_cast<long long>(time * _impl->frequency.QuadPart / 1000);
97 : #else
98 0 : const int sec = static_cast<int>(time / 1000) + 1;
99 0 : _impl->start.tv_sec -= sec;
100 0 : _impl->start.tv_nsec -= static_cast<int>((time - sec * 1000) * 1000000);
101 0 : if (_impl->start.tv_nsec > 1000000000)
102 : {
103 0 : _impl->start.tv_sec += 1;
104 0 : _impl->start.tv_nsec -= 1000000000;
105 : }
106 : #endif
107 0 : }
108 :
109 24 : float Clock::getTimef() const
110 : {
111 : #ifdef __APPLE__
112 : const int64_t elapsed = mach_absolute_time() - _impl->start;
113 : return (elapsed * _impl->timebaseInfo.numer / _impl->timebaseInfo.denom /
114 : 1000000.f);
115 : #elif defined(_WIN32)
116 : LARGE_INTEGER now;
117 : QueryPerformanceCounter(&now);
118 : return 1000.0f * (now.QuadPart - _impl->start.QuadPart) /
119 : _impl->frequency.QuadPart;
120 : #else
121 : struct timespec now;
122 24 : clock_gettime(CLOCK_REALTIME, &now);
123 24 : return (1000.0f * (now.tv_sec - _impl->start.tv_sec) +
124 24 : 0.000001f * (now.tv_nsec - _impl->start.tv_nsec));
125 : #endif
126 : }
127 :
128 4 : float Clock::resetTimef()
129 : {
130 : #ifdef __APPLE__
131 : const uint64_t now = mach_absolute_time();
132 : const int64_t elapsed = now - _impl->start;
133 : const float time = elapsed * _impl->timebaseInfo.numer /
134 : _impl->timebaseInfo.denom / 1000000.f;
135 : #elif defined(_WIN32)
136 : LARGE_INTEGER now;
137 : QueryPerformanceCounter(&now);
138 : const float time = 1000.0f * (now.QuadPart - _impl->start.QuadPart) /
139 : _impl->frequency.QuadPart;
140 : #else
141 : struct timespec now;
142 4 : clock_gettime(CLOCK_REALTIME, &now);
143 4 : const float time = (1000.0f * (now.tv_sec - _impl->start.tv_sec) +
144 4 : 0.000001f * (now.tv_nsec - _impl->start.tv_nsec));
145 : #endif
146 4 : _impl->start = now;
147 4 : return time;
148 : }
149 :
150 531635 : int64_t Clock::getTime64() const
151 : {
152 : #ifdef __APPLE__
153 : const int64_t elapsed = mach_absolute_time() - _impl->start;
154 : return (elapsed * _impl->timebaseInfo.numer / _impl->timebaseInfo.denom +
155 : 500000) /
156 : 1000000;
157 : #elif defined(_WIN32)
158 : LARGE_INTEGER now;
159 : QueryPerformanceCounter(&now);
160 : return (1000 * (now.QuadPart - _impl->start.QuadPart) +
161 : (_impl->frequency.QuadPart >> 1)) /
162 : _impl->frequency.QuadPart;
163 : #else
164 : struct timespec now;
165 531635 : clock_gettime(CLOCK_REALTIME, &now);
166 531652 : return (1000 * (now.tv_sec - _impl->start.tv_sec) +
167 531652 : int64_t(0.000001f * (now.tv_nsec - _impl->start.tv_nsec + 500000)));
168 : #endif
169 : }
170 :
171 1 : 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 1 : clock_gettime(CLOCK_REALTIME, &now);
185 1 : return (1000.0 * (now.tv_sec - _impl->start.tv_sec) +
186 1 : 0.000001 * (now.tv_nsec - _impl->start.tv_nsec));
187 : #endif
188 : }
189 : }
|