445 lines
12 KiB
C++
445 lines
12 KiB
C++
/* ========================================================================= *
|
|
* *
|
|
* OpenMesh *
|
|
* Copyright (c) 2001-2023, RWTH-Aachen University *
|
|
* Department of Computer Graphics and Multimedia *
|
|
* All rights reserved. *
|
|
* www.openmesh.org *
|
|
* *
|
|
*---------------------------------------------------------------------------*
|
|
* This file is part of OpenMesh. *
|
|
*---------------------------------------------------------------------------*
|
|
* *
|
|
* Redistribution and use in source and binary forms, with or without *
|
|
* modification, are permitted provided that the following conditions *
|
|
* are met: *
|
|
* *
|
|
* 1. Redistributions of source code must retain the above copyright notice, *
|
|
* this list of conditions and the following disclaimer. *
|
|
* *
|
|
* 2. Redistributions in binary form must reproduce the above copyright *
|
|
* notice, this list of conditions and the following disclaimer in the *
|
|
* documentation and/or other materials provided with the distribution. *
|
|
* *
|
|
* 3. Neither the name of the copyright holder nor the names of its *
|
|
* contributors may be used to endorse or promote products derived from *
|
|
* this software without specific prior written permission. *
|
|
* *
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
|
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
|
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
|
* *
|
|
* ========================================================================= */
|
|
|
|
|
|
|
|
#ifndef DOXY_IGNORE_THIS
|
|
// ----------------------------------------------------------------------------
|
|
#include <OpenMesh/Core/System/config.h>
|
|
#if defined(OM_CC_MIPS)
|
|
# include <math.h>
|
|
# include <stdio.h>
|
|
#else
|
|
# include <cmath>
|
|
# include <cstdio>
|
|
#endif
|
|
#include "Timer.hh"
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// ------------------------------------------------------------- namespace ----
|
|
|
|
namespace OpenMesh {
|
|
namespace Utils {
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
using namespace std;
|
|
|
|
// -------------------------------------------------------------- TimerImpl ----
|
|
// just a base class for the implementation
|
|
class TimerImpl
|
|
{
|
|
protected:
|
|
public:
|
|
TimerImpl() { ; }
|
|
virtual ~TimerImpl() { ; }
|
|
|
|
virtual void reset(void) = 0;
|
|
virtual void start(void) = 0;
|
|
virtual void stop(void) = 0;
|
|
virtual void cont(void) = 0;
|
|
virtual double seconds(void) const = 0;
|
|
};
|
|
|
|
// compiler and os dependent implementation
|
|
|
|
// ------------------------------------------------------------- windows 32 ----
|
|
#if defined(WIN32) && (defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined (__MINGW32__) )
|
|
|
|
#ifndef DOXY_IGNORE_THIS
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
class TimerImplWin32 : public TimerImpl
|
|
{
|
|
protected:
|
|
LARGE_INTEGER freq_;
|
|
LARGE_INTEGER count_;
|
|
LARGE_INTEGER start_;
|
|
|
|
public:
|
|
TimerImplWin32(void);
|
|
~TimerImplWin32(void) { ; }
|
|
|
|
virtual void reset(void) override;
|
|
virtual void start(void) override;
|
|
virtual void stop(void) override;
|
|
virtual void cont(void) override;
|
|
virtual double seconds(void) const override;
|
|
};
|
|
|
|
TimerImplWin32::TimerImplWin32(void)
|
|
{
|
|
if (QueryPerformanceFrequency(&freq_)==FALSE)
|
|
throw std::runtime_error("Performance counter of of stock!");
|
|
|
|
memset(&count_,0,sizeof(count_));
|
|
memset(&start_,0,sizeof(count_));
|
|
}
|
|
|
|
void TimerImplWin32::reset(void)
|
|
{
|
|
memset(&count_,0,sizeof(count_));
|
|
memset(&start_,0,sizeof(count_));
|
|
}
|
|
|
|
void TimerImplWin32::start(void)
|
|
{
|
|
reset();
|
|
QueryPerformanceCounter(&start_);
|
|
}
|
|
|
|
void TimerImplWin32::stop(void)
|
|
{
|
|
LARGE_INTEGER stop_;
|
|
|
|
QueryPerformanceCounter(&stop_);
|
|
count_.QuadPart += stop_.QuadPart - start_.QuadPart;
|
|
}
|
|
|
|
void TimerImplWin32::cont(void)
|
|
{
|
|
QueryPerformanceCounter(&start_);
|
|
}
|
|
|
|
double TimerImplWin32::seconds(void) const
|
|
{
|
|
return (double)count_.QuadPart/(double)freq_.QuadPart;
|
|
}
|
|
|
|
// ------------------------------------------------------------- posix time ----
|
|
#elif defined(__GNUC__) && defined(__POSIX__)
|
|
|
|
#ifndef DOXY_IGNORE_THIS
|
|
# include <time.h>
|
|
#endif
|
|
|
|
template <clockid_t N>
|
|
class TimerImplPosix : public TimerImpl
|
|
{
|
|
public:
|
|
TimerImplPosix() : id_(N), seconds_(0.0)
|
|
{ }
|
|
|
|
~TimerImplPosix()
|
|
{ }
|
|
|
|
virtual void reset(void) { seconds_ = 0.0; }
|
|
|
|
virtual void start(void) { seconds_ = 0.0; clock_gettime( id_, &start_ ); }
|
|
virtual void stop(void)
|
|
{
|
|
timespec stop;
|
|
clock_gettime( id_, &stop );
|
|
seconds_ += ( stop.tv_sec - start_.tv_sec );
|
|
seconds_ += ( (double(stop.tv_nsec-start_.tv_nsec)*1e-9) );
|
|
}
|
|
|
|
virtual void cont(void) { clock_gettime( id_, &start_ ); }
|
|
|
|
virtual double seconds() const { return seconds_; }
|
|
|
|
protected:
|
|
clockid_t id_;
|
|
double seconds_;
|
|
timespec start_;
|
|
};
|
|
|
|
// ----------------------------------------------------------- gettimeofday ----
|
|
#elif (defined(__GNUC__) && !defined(__FreeBSD__) || (defined(__INTEL_COMPILER) && !defined(WIN32))) && !defined(__MINGW32__)
|
|
|
|
# include <sys/time.h>
|
|
# include <sys/resource.h>
|
|
# include <unistd.h>
|
|
|
|
class TimerImplGToD: public TimerImpl
|
|
{
|
|
public:
|
|
TimerImplGToD() : seconds_(0.0)
|
|
{ }
|
|
|
|
~TimerImplGToD()
|
|
{ }
|
|
|
|
virtual void reset(void) override { seconds_ = 0.0; }
|
|
virtual void start(void) override { seconds_ = 0.0; gettimeofday( &start_, &tz_ ); }
|
|
|
|
virtual void stop(void) override
|
|
{
|
|
gettimeofday( &stop_, &tz_ );
|
|
|
|
seconds_ += (double)(stop_.tv_sec - start_.tv_sec);
|
|
seconds_ += (double)(stop_.tv_usec- start_.tv_usec)*1e-6;
|
|
}
|
|
|
|
virtual void cont(void) override { gettimeofday( &start_, &tz_); }
|
|
|
|
virtual double seconds() const override { return seconds_; }
|
|
|
|
private:
|
|
|
|
struct timeval start_, stop_;
|
|
struct timezone tz_;
|
|
|
|
double seconds_;
|
|
};
|
|
|
|
|
|
#else // ---------------------------------------- standard implementation ----
|
|
|
|
#include <time.h>
|
|
|
|
static const unsigned long clockticks = CLOCKS_PER_SEC;
|
|
|
|
class TimerImplStd : public TimerImpl
|
|
{
|
|
public:
|
|
TimerImplStd() : freq_(clockticks),count_(0),start_(0) { }
|
|
~TimerImplStd() { ; }
|
|
|
|
virtual void reset(void) override { count_ = 0; }
|
|
virtual void start(void) override { count_ = 0; start_ = clock(); }
|
|
virtual void stop(void) override;
|
|
virtual void cont(void) override { start_ = clock(); }
|
|
virtual double seconds(void) const override { return (double)count_/(double)freq_; }
|
|
|
|
protected:
|
|
unsigned long freq_;
|
|
unsigned long count_;
|
|
unsigned long start_;
|
|
};
|
|
|
|
void TimerImplStd::stop(void)
|
|
{
|
|
unsigned long stop_ = clock();
|
|
count_ += stop_-start_;
|
|
}
|
|
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------- Timer ----
|
|
|
|
Timer::Timer(void) :
|
|
state_(Stopped)
|
|
{
|
|
#if defined(WIN32) && (defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__MINGW32__))
|
|
impl_ = new TimerImplWin32;
|
|
#elif defined(__GNUC__) && defined(__POSIX__)
|
|
// CLOCK_REALTIME
|
|
// CLOCK_MONOTONIC - ?
|
|
// CLOCK_REALTIME_HR - RTlinux
|
|
// CLOCK_MONOTONIC_HR - ?
|
|
# if defined(CLOCK_REALTIME_HR)
|
|
impl_ = new TimerImplPosix<CLOCK_REALTIME_HR>;
|
|
# else
|
|
impl_ = new TimerImplPosix<CLOCK_REALTIME>;
|
|
# endif
|
|
#elif (defined(__GNUC__) && !defined(__FreeBSD__) || (defined(__INTEL_COMPILER) && !defined(WIN32)) ) && !defined(__MINGW32__)
|
|
impl_ = new TimerImplGToD;
|
|
#else
|
|
impl_ = new TimerImplStd;
|
|
#endif
|
|
|
|
}
|
|
|
|
Timer::~Timer(void)
|
|
{
|
|
delete impl_;
|
|
state_ = Stopped;
|
|
}
|
|
|
|
void Timer::reset(void)
|
|
{
|
|
state_ = Stopped;
|
|
impl_->reset();
|
|
}
|
|
|
|
void Timer::start(void)
|
|
{
|
|
state_ = Running;
|
|
impl_->start();
|
|
}
|
|
|
|
void Timer::stop(void)
|
|
{
|
|
impl_->stop();
|
|
state_ = Stopped;
|
|
}
|
|
|
|
void Timer::cont(void)
|
|
{
|
|
impl_->cont();
|
|
state_ = Running;
|
|
}
|
|
|
|
double Timer::seconds(void) const
|
|
{
|
|
return state_==Stopped ? impl_->seconds() : 0.0;
|
|
}
|
|
|
|
std::string Timer::as_string(Timer::Format format)
|
|
{
|
|
if (state_ == Running)
|
|
return "Running";
|
|
return as_string(impl_->seconds(),format);
|
|
}
|
|
|
|
std::string Timer::as_string(double seconds, Timer::Format format)
|
|
{
|
|
char string[32];
|
|
|
|
double fraction;
|
|
double integer;
|
|
unsigned long t;
|
|
// double rest;
|
|
short hour,min,sec;
|
|
bool negative = false;
|
|
|
|
if ( seconds < 0 )
|
|
{
|
|
negative = true;
|
|
seconds *= -1;
|
|
}
|
|
|
|
fraction = modf(seconds,&integer);
|
|
|
|
t = (unsigned long)integer;
|
|
|
|
hour = short( t / 3600L );
|
|
t %= 3600L;
|
|
min = short( t / 60L );
|
|
t %= 60L;
|
|
sec = short( t );
|
|
// rest = (double)t + fraction;
|
|
|
|
char *ptr = string;
|
|
if (negative)
|
|
*ptr++ = '-';
|
|
|
|
switch(format)
|
|
{
|
|
case Timer::Automatic:
|
|
if (hour)
|
|
ptr += sprintf(ptr,"%02dh:",hour);
|
|
|
|
if (min)
|
|
ptr += sprintf(ptr,"%02dm:",min);
|
|
else if (ptr>string && hour)
|
|
ptr += sprintf(ptr,"00m:");
|
|
|
|
if (sec)
|
|
ptr += sprintf(ptr,"%02d",sec);
|
|
else if (ptr>string && min)
|
|
ptr += sprintf(ptr,"00");
|
|
|
|
if (!hour && !min) // higher resolution necessary
|
|
{
|
|
if (ptr > string && sec)
|
|
{
|
|
sprintf(ptr,".%.3fs",fraction);
|
|
ptr++;
|
|
while(*(ptr+2))
|
|
{
|
|
*ptr = *(ptr+2);
|
|
ptr++;
|
|
}
|
|
*ptr = '\0';
|
|
}
|
|
else if ( fraction * 1e2 > 0.1)
|
|
sprintf(ptr,"%.3fcs",fraction*1.e2);
|
|
else if ( fraction * 1e3 > 0.1)
|
|
sprintf(ptr,"%.3fms",fraction*1.e3);
|
|
else if ( fraction * 1e6 > 0.1)
|
|
sprintf(ptr,"%.1f\xb5s",fraction*1.e6);
|
|
else if ( fraction * 1e9 > 0.1)
|
|
sprintf(ptr,"%.1fns",fraction*1.e9);
|
|
else
|
|
sprintf(ptr,"%.1fps",fraction*1.e12);
|
|
} else // append a 's' for seconds!
|
|
{
|
|
ptr[0] = 's';
|
|
ptr[1] = '\0';
|
|
}
|
|
break;
|
|
case Timer::Long:
|
|
ptr += sprintf(ptr,"%02dh:%02dm:%02d",hour,min,sec);
|
|
sprintf(ptr,".%.12fs",fraction);
|
|
ptr++;
|
|
while(*(ptr+2))
|
|
{
|
|
*ptr = *(ptr+2);
|
|
ptr++;
|
|
}
|
|
*ptr = '\0';
|
|
break;
|
|
case Timer::Hours:
|
|
sprintf(ptr,"%02dh:%02dm:%02ds",hour,min,sec); break;
|
|
case Timer::Minutes:
|
|
ptr += sprintf(ptr,"%02dm:%02d", min, sec);
|
|
sprintf(ptr,".%.2fs",fraction);
|
|
ptr++;
|
|
while(*(ptr+2))
|
|
{
|
|
*ptr = *(ptr+2);
|
|
ptr++;
|
|
}
|
|
*ptr = '\0';
|
|
break;
|
|
case Timer::Seconds: sprintf(ptr,"%.3fs",seconds); break;
|
|
case Timer::HSeconds: sprintf(ptr,"%.3fcs",seconds*1e2); break;
|
|
case Timer::MSeconds: sprintf(ptr,"%.3fms",seconds*1e3); break;
|
|
case Timer::MicroSeconds: sprintf(ptr,"%.1f\xb5s",seconds*1e6); break;
|
|
case Timer::NanoSeconds: sprintf(ptr,"%.1fns",seconds*1e9); break;
|
|
}
|
|
return string;
|
|
}
|
|
|
|
// ============================================================================
|
|
} // END_NS_UTILS
|
|
} // END_NS_OPENMESH
|
|
// ----------------------------------------------------------------------------
|
|
#endif // DOXY_IGNORE_THIS
|
|
// ============================================================================
|
|
// end of file Timer.cc
|
|
// ============================================================================
|
|
|