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 // ----------------------------------------------------------------------------
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 
void reset(void)
Reset the timer.
STL namespace.
std::string as_string(Format format=Automatic)
double seconds(void) const
Returns measured time in seconds, if the timer is in state &#39;Stopped&#39;.
void stop(void)
Stop measurement.
void cont(void)
Continue measurement.
Format
Formatting options for member Timer::as_string()
Definition: Timer.hh:87
void start(void)
Start measurement.