Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 stop(void)
Stop measurement.
std::string as_string(Format format=Automatic)
void reset(void)
Reset the timer.
void start(void)
Start measurement.
double seconds(void) const
Returns measured time in seconds, if the timer is in state 'Stopped'.
STL namespace.
void cont(void)
Continue measurement.
Format
Formatting options for member Timer::as_string()
Definition: Timer.hh:92