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