Developer Documentation

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