Developer Documentation
Loading...
Searching...
No Matches
Timer.cc
1/* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2025, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openmesh.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenMesh. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 * ========================================================================= */
41
42
43
44#ifndef DOXY_IGNORE_THIS
45// ----------------------------------------------------------------------------
47#if defined(OM_CC_MIPS)
48# include <math.h>
49# include <stdio.h>
50#else
51# include <cmath>
52# include <cstdio>
53#endif
54// ---windows 32 --------------------------------------------------------------
55#if defined(WIN32) && (defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined (__MINGW32__) )
56# include <windows.h>
57// ---posix time --------------------------------------------------------------
58#elif defined(__GNUC__) && defined(__POSIX__)
59# include <time.h>
60// ---gettimeofday ------------------------------------------------------------
61#elif (defined(__GNUC__) && !defined(__FreeBSD__) || (defined(__INTEL_COMPILER) && !defined(WIN32))) && !defined(__MINGW32__)
62
63# include <sys/time.h>
64# include <sys/resource.h>
65# include <unistd.h>
66// ---standard implementation -------------------------------------------------
67#else
68# include <time.h>
69#endif
70
71#include "Timer.hh"
72// ----------------------------------------------------------------------------
73
74// ------------------------------------------------------------- namespace ----
75
76namespace OpenMesh {
77namespace Utils {
78
79
80// ----------------------------------------------------------------------------
81
82using namespace std;
83
84// -------------------------------------------------------------- TimerImpl ----
85// just a base class for the implementation
86class TimerImpl
87{
88protected:
89public:
90 TimerImpl() { ; }
91 virtual ~TimerImpl() { ; }
92
93 virtual void reset(void) = 0;
94 virtual void start(void) = 0;
95 virtual void stop(void) = 0;
96 virtual void cont(void) = 0;
97 virtual double seconds(void) const = 0;
98};
99
100// compiler and os dependent implementation
101
102// ------------------------------------------------------------- windows 32 ----
103#if defined(WIN32) && (defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined (__MINGW32__) )
104
105class TimerImplWin32 : public TimerImpl
106{
107protected:
108 LARGE_INTEGER freq_;
109 LARGE_INTEGER count_;
110 LARGE_INTEGER start_;
111
112public:
113 TimerImplWin32(void);
114 ~TimerImplWin32(void) { ; }
115
116 virtual void reset(void) override;
117 virtual void start(void) override;
118 virtual void stop(void) override;
119 virtual void cont(void) override;
120 virtual double seconds(void) const override;
121};
122
123TimerImplWin32::TimerImplWin32(void)
124{
125 if (QueryPerformanceFrequency(&freq_)==FALSE)
126 throw std::runtime_error("Performance counter of of stock!");
127
128 memset(&count_,0,sizeof(count_));
129 memset(&start_,0,sizeof(count_));
130}
131
132void TimerImplWin32::reset(void)
133{
134 memset(&count_,0,sizeof(count_));
135 memset(&start_,0,sizeof(count_));
136}
137
138void TimerImplWin32::start(void)
139{
140 reset();
141 QueryPerformanceCounter(&start_);
142}
143
144void TimerImplWin32::stop(void)
145{
146 LARGE_INTEGER stop_;
147
148 QueryPerformanceCounter(&stop_);
149 count_.QuadPart += stop_.QuadPart - start_.QuadPart;
150}
151
152void TimerImplWin32::cont(void)
153{
154 QueryPerformanceCounter(&start_);
155}
156
157double TimerImplWin32::seconds(void) const
158{
159 return (double)count_.QuadPart/(double)freq_.QuadPart;
160}
161
162// ------------------------------------------------------------- posix time ----
163#elif defined(__GNUC__) && defined(__POSIX__)
164
165template <clockid_t N>
166class TimerImplPosix : public TimerImpl
167{
168public:
169 TimerImplPosix() : id_(N), seconds_(0.0)
170 { }
171
172 ~TimerImplPosix()
173 { }
174
175 virtual void reset(void) override { seconds_ = 0.0; }
176
177 virtual void start(void) override { seconds_ = 0.0; clock_gettime( id_, &start_ ); }
178 virtual void stop(void) override
179 {
180 timespec stop;
181 clock_gettime( id_, &stop );
182 seconds_ += ( stop.tv_sec - start_.tv_sec );
183 seconds_ += ( (double(stop.tv_nsec-start_.tv_nsec)*1e-9) );
184 }
185
186 virtual void cont(void) override { clock_gettime( id_, &start_ ); }
187
188 virtual double seconds() override const { return seconds_; }
189
190protected:
191 clockid_t id_;
192 double seconds_;
193 timespec start_;
194};
195
196// ----------------------------------------------------------- gettimeofday ----
197#elif (defined(__GNUC__) && !defined(__FreeBSD__) || (defined(__INTEL_COMPILER) && !defined(WIN32))) && !defined(__MINGW32__)
198
199class TimerImplGToD: public TimerImpl
200{
201public:
202 TimerImplGToD() : seconds_(0.0)
203 { }
204
205 ~TimerImplGToD()
206 { }
207
208 virtual void reset(void) override { seconds_ = 0.0; }
209 virtual void start(void) override { seconds_ = 0.0; gettimeofday( &start_, &tz_ ); }
210
211 virtual void stop(void) override
212 {
213 gettimeofday( &stop_, &tz_ );
214
215 seconds_ += (double)(stop_.tv_sec - start_.tv_sec);
216 seconds_ += (double)(stop_.tv_usec- start_.tv_usec)*1e-6;
217 }
218
219 virtual void cont(void) override { gettimeofday( &start_, &tz_); }
220
221 virtual double seconds() const override { return seconds_; }
222
223private:
224
225 struct timeval start_, stop_;
226 struct timezone tz_;
227
228 double seconds_;
229};
230
231
232#else // ---------------------------------------- standard implementation ----
233
234static const unsigned long clockticks = CLOCKS_PER_SEC;
235
236class TimerImplStd : public TimerImpl
237{
238public:
239 TimerImplStd() : freq_(clockticks),count_(0),start_(0) { }
240 ~TimerImplStd() { ; }
241
242 virtual void reset(void) override { count_ = 0; }
243 virtual void start(void) override { count_ = 0; start_ = clock(); }
244 virtual void stop(void) override;
245 virtual void cont(void) override { start_ = clock(); }
246 virtual double seconds(void) const override { return (double)count_/(double)freq_; }
247
248protected:
249 unsigned long freq_;
250 unsigned long count_;
251 unsigned long start_;
252};
253
254void TimerImplStd::stop(void)
255{
256 unsigned long stop_ = clock();
257 count_ += stop_-start_;
258}
259
260#endif
261
262// ----------------------------------------------------------------- Timer ----
263
264Timer::Timer(void) :
265 state_(Stopped)
266{
267#if defined(WIN32) && (defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__MINGW32__))
268 impl_ = new TimerImplWin32;
269#elif defined(__GNUC__) && defined(__POSIX__)
270// CLOCK_REALTIME
271// CLOCK_MONOTONIC - ?
272// CLOCK_REALTIME_HR - RTlinux
273// CLOCK_MONOTONIC_HR - ?
274# if defined(CLOCK_REALTIME_HR)
275 impl_ = new TimerImplPosix<CLOCK_REALTIME_HR>;
276# else
277 impl_ = new TimerImplPosix<CLOCK_REALTIME>;
278# endif
279#elif (defined(__GNUC__) && !defined(__FreeBSD__) || (defined(__INTEL_COMPILER) && !defined(WIN32)) ) && !defined(__MINGW32__)
280 impl_ = new TimerImplGToD;
281#else
282 impl_ = new TimerImplStd;
283#endif
284
285}
286
287Timer::~Timer(void)
288{
289 delete impl_;
290 state_ = Stopped;
291}
292
293void Timer::reset(void)
294{
295 state_ = Stopped;
296 impl_->reset();
297}
298
299void Timer::start(void)
300{
301 state_ = Running;
302 impl_->start();
303}
304
305void Timer::stop(void)
306{
307 impl_->stop();
308 state_ = Stopped;
309}
310
311void Timer::cont(void)
312{
313 impl_->cont();
314 state_ = Running;
315}
316
317double Timer::seconds(void) const
318{
319 return state_==Stopped ? impl_->seconds() : 0.0;
320}
321
322std::string Timer::as_string(Timer::Format format)
323{
324 if (state_ == Running)
325 return "Running";
326 return as_string(impl_->seconds(),format);
327}
328
329std::string Timer::as_string(double seconds, Timer::Format format)
330{
331 char string[32];
332
333 double fraction;
334 double integer;
335 unsigned long t;
336// double rest;
337 short hour,min,sec;
338 bool negative = false;
339
340 if ( seconds < 0 )
341 {
342 negative = true;
343 seconds *= -1;
344 }
345
346 fraction = modf(seconds,&integer);
347
348 t = (unsigned long)integer;
349
350 hour = short( t / 3600L );
351 t %= 3600L;
352 min = short( t / 60L );
353 t %= 60L;
354 sec = short( t );
355// rest = (double)t + fraction;
356
357 char *ptr = string;
358 if (negative)
359 *ptr++ = '-';
360
361 switch(format)
362 {
363 case Timer::Automatic:
364 if (hour)
365 ptr += sprintf(ptr,"%02dh:",hour);
366
367 if (min)
368 ptr += sprintf(ptr,"%02dm:",min);
369 else if (ptr>string && hour)
370 ptr += sprintf(ptr,"00m:");
371
372 if (sec)
373 ptr += sprintf(ptr,"%02d",sec);
374 else if (ptr>string && min)
375 ptr += sprintf(ptr,"00");
376
377 if (!hour && !min) // higher resolution necessary
378 {
379 if (ptr > string && sec)
380 {
381 sprintf(ptr,".%.3fs",fraction);
382 ptr++;
383 while(*(ptr+2))
384 {
385 *ptr = *(ptr+2);
386 ptr++;
387 }
388 *ptr = '\0';
389 }
390 else if ( fraction * 1e2 > 0.1)
391 sprintf(ptr,"%.3fcs",fraction*1.e2);
392 else if ( fraction * 1e3 > 0.1)
393 sprintf(ptr,"%.3fms",fraction*1.e3);
394 else if ( fraction * 1e6 > 0.1)
395 sprintf(ptr,"%.1f\xb5s",fraction*1.e6);
396 else if ( fraction * 1e9 > 0.1)
397 sprintf(ptr,"%.1fns",fraction*1.e9);
398 else
399 sprintf(ptr,"%.1fps",fraction*1.e12);
400 } else // append a 's' for seconds!
401 {
402 ptr[0] = 's';
403 ptr[1] = '\0';
404 }
405 break;
406 case Timer::Long:
407 ptr += sprintf(ptr,"%02dh:%02dm:%02d",hour,min,sec);
408 sprintf(ptr,".%.12fs",fraction);
409 ptr++;
410 while(*(ptr+2))
411 {
412 *ptr = *(ptr+2);
413 ptr++;
414 }
415 *ptr = '\0';
416 break;
417 case Timer::Hours:
418 sprintf(ptr,"%02dh:%02dm:%02ds",hour,min,sec); break;
419 case Timer::Minutes:
420 ptr += sprintf(ptr,"%02dm:%02d", min, sec);
421 sprintf(ptr,".%.2fs",fraction);
422 ptr++;
423 while(*(ptr+2))
424 {
425 *ptr = *(ptr+2);
426 ptr++;
427 }
428 *ptr = '\0';
429 break;
430 case Timer::Seconds: sprintf(ptr,"%.3fs",seconds); break;
431 case Timer::HSeconds: sprintf(ptr,"%.3fcs",seconds*1e2); break;
432 case Timer::MSeconds: sprintf(ptr,"%.3fms",seconds*1e3); break;
433 case Timer::MicroSeconds: sprintf(ptr,"%.1f\xb5s",seconds*1e6); break;
434 case Timer::NanoSeconds: sprintf(ptr,"%.1fns",seconds*1e9); break;
435 }
436 return string;
437}
438
439// ============================================================================
440} // END_NS_UTILS
441} // END_NS_OPENMESH
442// ----------------------------------------------------------------------------
443#endif // DOXY_IGNORE_THIS
444// ============================================================================
445// end of file Timer.cc
446// ============================================================================
447