Skip to content
Snippets Groups Projects
timer.hh 3.57 KiB
Newer Older
  • Learn to ignore specific revisions
  • Peter Bastian's avatar
    Peter Bastian committed
    // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
    // vi: set et ts=4 sw=2 sts=2:
    
    #ifndef DUNE_TIMER_HH
    #define DUNE_TIMER_HH
    
    
    #ifndef TIMER_USE_STD_CLOCK
    
    // headers for getrusage(2)
    #include <sys/resource.h>
    
    #include <cstring>
    
    
    // access to errno in C++
    #include <cerrno>
    
    #include "exceptions.hh"
    
    namespace Dune {
    
      /** @addtogroup Common
         @{
       */
    
      /*! \file
    
          \brief A simple timing class.
    
      /** \brief %Exception thrown by the Timer class */
    
      class TimerError : public SystemError {} ;
    
    
      /** \brief A simple stop watch
    
         This class reports the elapsed user-time, i.e. time spent computing,
    
         after the last call to Timer::reset(). The results are seconds and
         fractional seconds. Note that the resolution of the timing depends
         on your OS kernel which should be somewhere in the milisecond range.
    
         The class is basically a wrapper for the libc-function getrusage()
    
       */
    
    Peter Bastian's avatar
    Peter Bastian committed
      class Timer
      {
      public:
    
        /** \brief A new timer, create and reset
         *
         * \param startImmediately If true (default) the timer starts counting immediately
         */
        Timer (bool startImmediately=true) throw(TimerError)
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    
          isRunning_ = startImmediately;
    
        //! Reset timer while keeping the running/stoped state
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    
          sumElapsed_ = 0.0;
          storedLastElapsed_ = 0.0;
          rawReset();
        }
    
    
        //! Start the timer and continue measurement if it is not running. Otherwise do nothing.
        void start() throw (TimerError)
        {
          if (not (isRunning_))
          {
            rawReset();
            isRunning_ = true;
          }
        }
    
    
        //! Get elapsed user-time from last reset until now/last stop in seconds.
        double elapsed () const throw (TimerError)
        {
          // if timer is running add the time elapsed since last start to sum
          if (isRunning_)
            return sumElapsed_ + lastElapsed();
    
          return sumElapsed_;
        }
    
    
        //! Get elapsed user-time from last start until now/last stop in seconds.
        double lastElapsed () const throw (TimerError)
        {
          // if timer is running return the current value
          if (isRunning_)
            return rawElapsed();
    
          // if timer is not running return stored value from last run
          return storedLastElapsed_;
        }
    
    
        //! Stop the timer and return elapsed().
        double stop() throw (TimerError)
        {
          if (isRunning_)
          {
            // update storedLastElapsed_ and  sumElapsed_ and stop timer
            storedLastElapsed_ = lastElapsed();
            sumElapsed_ += storedLastElapsed_;
            isRunning_ = false;
          }
          return elapsed();
        }
    
    
      private:
    
        bool isRunning_;
        double sumElapsed_;
        double storedLastElapsed_;
    
    
    
    #ifdef TIMER_USE_STD_CLOCK
    
        void rawReset() throw (TimerError)
        {
    
          cstart = std::clock();
    
        }
    
        double rawElapsed () const throw (TimerError)
        {
          return (std::clock()-cstart) / static_cast<double>(CLOCKS_PER_SEC);
        }
    
        std::clock_t cstart;
    
        void rawReset() throw (TimerError)
        {
    
          rusage ru;
          if (getrusage(RUSAGE_SELF, &ru))
            DUNE_THROW(TimerError, strerror(errno));
          cstart = ru.ru_utime;
    
        double rawElapsed () const throw (TimerError)
    
          rusage ru;
          if (getrusage(RUSAGE_SELF, &ru))
            DUNE_THROW(TimerError, strerror(errno));
          return 1.0 * (ru.ru_utime.tv_sec - cstart.tv_sec) + (ru.ru_utime.tv_usec - cstart.tv_usec) / (1000.0 * 1000.0);
    
    Peter Bastian's avatar
    Peter Bastian committed
    
      /** @} end documentation */
    
    } // end namespace
    
    #endif