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#include "Timer.hh"
55// ----------------------------------------------------------------------------
56
57// ------------------------------------------------------------- namespace ----
58
59namespace OpenMesh {
60namespace Utils {
61
62
63// ----------------------------------------------------------------------------
64
65using namespace std;
66
67// -------------------------------------------------------------- TimerImpl ----
68// just a base class for the implementation
69class TimerImpl
70{
71protected:
72public:
73 TimerImpl() { ; }
74 virtual ~TimerImpl() { ; }
75
76 virtual void reset(void) = 0;
77 virtual void start(void) = 0;
78 virtual void stop(void) = 0;
79 virtual void cont(void) = 0;
80 virtual double seconds(void) const = 0;
81};
82
83// compiler and os dependent implementation
84
85// ------------------------------------------------------------- windows 32 ----
86#if defined(WIN32) && (defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined (__MINGW32__) )
87
88#ifndef DOXY_IGNORE_THIS
89#include <windows.h>
90#endif
91
92class TimerImplWin32 : public TimerImpl
93{
94protected:
95 LARGE_INTEGER freq_;
96 LARGE_INTEGER count_;
97 LARGE_INTEGER start_;
98
99public:
100 TimerImplWin32(void);
101 ~TimerImplWin32(void) { ; }
102
103 virtual void reset(void) override;
104 virtual void start(void) override;
105 virtual void stop(void) override;
106 virtual void cont(void) override;
107 virtual double seconds(void) const override;
108};
109
110TimerImplWin32::TimerImplWin32(void)
111{
112 if (QueryPerformanceFrequency(&freq_)==FALSE)
113 throw std::runtime_error("Performance counter of of stock!");
114
115 memset(&count_,0,sizeof(count_));
116 memset(&start_,0,sizeof(count_));
117}
118
119void TimerImplWin32::reset(void)
120{
121 memset(&count_,0,sizeof(count_));
122 memset(&start_,0,sizeof(count_));
123}
124
125void TimerImplWin32::start(void)
126{
127 reset();
128 QueryPerformanceCounter(&start_);
129}
130
131void TimerImplWin32::stop(void)
132{
133 LARGE_INTEGER stop_;
134
135 QueryPerformanceCounter(&stop_);
136 count_.QuadPart += stop_.QuadPart - start_.QuadPart;
137}
138
139void TimerImplWin32::cont(void)
140{
141 QueryPerformanceCounter(&start_);
142}
143
144double TimerImplWin32::seconds(void) const
145{
146 return (double)count_.QuadPart/(double)freq_.QuadPart;
147}
148
149// ------------------------------------------------------------- posix time ----
150#elif defined(__GNUC__) && defined(__POSIX__)
151
152#ifndef DOXY_IGNORE_THIS
153# include <time.h>
154#endif
155
156template <clockid_t N>
157class TimerImplPosix : public TimerImpl
158{
159public:
160 TimerImplPosix() : id_(N), seconds_(0.0)
161 { }
162
163 ~TimerImplPosix()
164 { }
165
166 virtual void reset(void) override { seconds_ = 0.0; }
167
168 virtual void start(void) override { seconds_ = 0.0; clock_gettime( id_, &start_ ); }
169 virtual void stop(void) override
170 {
171 timespec stop;
172 clock_gettime( id_, &stop );
173 seconds_ += ( stop.tv_sec - start_.tv_sec );
174 seconds_ += ( (double(stop.tv_nsec-start_.tv_nsec)*1e-9) );
175 }
176
177 virtual void cont(void) override { clock_gettime( id_, &start_ ); }
178
179 virtual double seconds() override const { return seconds_; }
180
181protected:
182 clockid_t id_;
183 double seconds_;
184 timespec start_;
185};
186
187// ----------------------------------------------------------- gettimeofday ----
188#elif (defined(__GNUC__) && !defined(__FreeBSD__) || (defined(__INTEL_COMPILER) && !defined(WIN32))) && !defined(__MINGW32__)
189
190# include <sys/time.h>
191# include <sys/resource.h>
192# include <unistd.h>
193
194class TimerImplGToD: public TimerImpl
195{
196public:
197 TimerImplGToD() : seconds_(0.0)
198 { }
199
200 ~TimerImplGToD()
201 { }
202
203 virtual void reset(void) override { seconds_ = 0.0; }
204 virtual void start(void) override { seconds_ = 0.0; gettimeofday( &start_, &tz_ ); }
205
206 virtual void stop(void) override
207 {
208 gettimeofday( &stop_, &tz_ );
209
210 seconds_ += (double)(stop_.tv_sec - start_.tv_sec);
211 seconds_ += (double)(stop_.tv_usec- start_.tv_usec)*1e-6;
212 }
213
214 virtual void cont(void) override { gettimeofday( &start_, &tz_); }
215
216 virtual double seconds() const override { return seconds_; }
217
218private:
219
220 struct timeval start_, stop_;
221 struct timezone tz_;
222
223 double seconds_;
224};
225
226
227#else // ---------------------------------------- standard implementation ----
228
229#include <time.h>
230
231static const unsigned long clockticks = CLOCKS_PER_SEC;
232
233class TimerImplStd : public TimerImpl
234{
235public:
236 TimerImplStd() : freq_(clockticks),count_(0),start_(0) { }
237 ~TimerImplStd() { ; }
238
239 virtual void reset(void) override { count_ = 0; }
240 virtual void start(void) override { count_ = 0; start_ = clock(); }
241 virtual void stop(void) override;
242 virtual void cont(void) override { start_ = clock(); }
243 virtual double seconds(void) const override { return (double)count_/(double)freq_; }
244
245protected:
246 unsigned long freq_;
247 unsigned long count_;
248 unsigned long start_;
249};
250
251void TimerImplStd::stop(void)
252{
253 unsigned long stop_ = clock();
254 count_ += stop_-start_;
255}
256
257#endif
258
259// ----------------------------------------------------------------- Timer ----
260
261Timer::Timer(void) :
262 state_(Stopped)
263{
264#if defined(WIN32) && (defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__MINGW32__))
265 impl_ = new TimerImplWin32;
266#elif defined(__GNUC__) && defined(__POSIX__)
267// CLOCK_REALTIME
268// CLOCK_MONOTONIC - ?
269// CLOCK_REALTIME_HR - RTlinux
270// CLOCK_MONOTONIC_HR - ?
271# if defined(CLOCK_REALTIME_HR)
272 impl_ = new TimerImplPosix<CLOCK_REALTIME_HR>;
273# else
274 impl_ = new TimerImplPosix<CLOCK_REALTIME>;
275# endif
276#elif (defined(__GNUC__) && !defined(__FreeBSD__) || (defined(__INTEL_COMPILER) && !defined(WIN32)) ) && !defined(__MINGW32__)
277 impl_ = new TimerImplGToD;
278#else
279 impl_ = new TimerImplStd;
280#endif
281
282}
283
284Timer::~Timer(void)
285{
286 delete impl_;
287 state_ = Stopped;
288}
289
290void Timer::reset(void)
291{
292 state_ = Stopped;
293 impl_->reset();
294}
295
296void Timer::start(void)
297{
298 state_ = Running;
299 impl_->start();
300}
301
302void Timer::stop(void)
303{
304 impl_->stop();
305 state_ = Stopped;
306}
307
308void Timer::cont(void)
309{
310 impl_->cont();
311 state_ = Running;
312}
313
314double Timer::seconds(void) const
315{
316 return state_==Stopped ? impl_->seconds() : 0.0;
317}
318
319std::string Timer::as_string(Timer::Format format)
320{
321 if (state_ == Running)
322 return "Running";
323 return as_string(impl_->seconds(),format);
324}
325
326std::string Timer::as_string(double seconds, Timer::Format format)
327{
328 char string[32];
329
330 double fraction;
331 double integer;
332 unsigned long t;
333// double rest;
334 short hour,min,sec;
335 bool negative = false;
336
337 if ( seconds < 0 )
338 {
339 negative = true;
340 seconds *= -1;
341 }
342
343 fraction = modf(seconds,&integer);
344
345 t = (unsigned long)integer;
346
347 hour = short( t / 3600L );
348 t %= 3600L;
349 min = short( t / 60L );
350 t %= 60L;
351 sec = short( t );
352// rest = (double)t + fraction;
353
354 char *ptr = string;
355 if (negative)
356 *ptr++ = '-';
357
358 switch(format)
359 {
360 case Timer::Automatic:
361 if (hour)
362 ptr += sprintf(ptr,"%02dh:",hour);
363
364 if (min)
365 ptr += sprintf(ptr,"%02dm:",min);
366 else if (ptr>string && hour)
367 ptr += sprintf(ptr,"00m:");
368
369 if (sec)
370 ptr += sprintf(ptr,"%02d",sec);
371 else if (ptr>string && min)
372 ptr += sprintf(ptr,"00");
373
374 if (!hour && !min) // higher resolution necessary
375 {
376 if (ptr > string && sec)
377 {
378 sprintf(ptr,".%.3fs",fraction);
379 ptr++;
380 while(*(ptr+2))
381 {
382 *ptr = *(ptr+2);
383 ptr++;
384 }
385 *ptr = '\0';
386 }
387 else if ( fraction * 1e2 > 0.1)
388 sprintf(ptr,"%.3fcs",fraction*1.e2);
389 else if ( fraction * 1e3 > 0.1)
390 sprintf(ptr,"%.3fms",fraction*1.e3);
391 else if ( fraction * 1e6 > 0.1)
392 sprintf(ptr,"%.1f\xb5s",fraction*1.e6);
393 else if ( fraction * 1e9 > 0.1)
394 sprintf(ptr,"%.1fns",fraction*1.e9);
395 else
396 sprintf(ptr,"%.1fps",fraction*1.e12);
397 } else // append a 's' for seconds!
398 {
399 ptr[0] = 's';
400 ptr[1] = '\0';
401 }
402 break;
403 case Timer::Long:
404 ptr += sprintf(ptr,"%02dh:%02dm:%02d",hour,min,sec);
405 sprintf(ptr,".%.12fs",fraction);
406 ptr++;
407 while(*(ptr+2))
408 {
409 *ptr = *(ptr+2);
410 ptr++;
411 }
412 *ptr = '\0';
413 break;
414 case Timer::Hours:
415 sprintf(ptr,"%02dh:%02dm:%02ds",hour,min,sec); break;
416 case Timer::Minutes:
417 ptr += sprintf(ptr,"%02dm:%02d", min, sec);
418 sprintf(ptr,".%.2fs",fraction);
419 ptr++;
420 while(*(ptr+2))
421 {
422 *ptr = *(ptr+2);
423 ptr++;
424 }
425 *ptr = '\0';
426 break;
427 case Timer::Seconds: sprintf(ptr,"%.3fs",seconds); break;
428 case Timer::HSeconds: sprintf(ptr,"%.3fcs",seconds*1e2); break;
429 case Timer::MSeconds: sprintf(ptr,"%.3fms",seconds*1e3); break;
430 case Timer::MicroSeconds: sprintf(ptr,"%.1f\xb5s",seconds*1e6); break;
431 case Timer::NanoSeconds: sprintf(ptr,"%.1fns",seconds*1e9); break;
432 }
433 return string;
434}
435
436// ============================================================================
437} // END_NS_UTILS
438} // END_NS_OPENMESH
439// ----------------------------------------------------------------------------
440#endif // DOXY_IGNORE_THIS
441// ============================================================================
442// end of file Timer.cc
443// ============================================================================
444