Skip navigation links
IT services and product development
Menu
TwoLogs
IT services and product development

Source code for C_HiResTimer

Download

The source files for this module are listed below.  You can also download the module C_HiResTimer as a zip archive; this archive contains all the source files and documentation.

Description

CHiResTimer is a timer class that measures time using the highest accuracy timer available on the system.

Information

CHiResTimer is easy to use.  You create an object of the timer class, and consecutively ask it if the timer is supported (not all systems support a high resolution timer).  If the timer is supported, you can call Start, Stop and Reset at will.  You can also specify that the time measurement must be started when the timer itself is created.

Once the timer has been started, you can call GetInterval to determine the interval that has passed since you called Start.  Intervals are measured in seconds.  Once the timer is stopped, the interval will remain unchanged.  You can query for the state of the timer by calling it's GetState method.

Note that when you query for the interval when the timer is still ticking, there will be some extra overhead due to the fact that a temporary 'stop'-time needs to be generated.  Thus, having a lot of interval checks on a running timer somewhat decreases it's acuracy.  Also, if the high-resolution timer is not supported by the system, all returned intervals will be 0.

Files

Each file belonging to this source code module is listed below.

HiResTimer.h

/*******************************************************************************

  Version: 1
  Author:  Carl Colijn, TwoLogs
  Contact: c.colijn@twologs.com
  Source:  http://www.twologs.com/sourcecode

  This code is freely distributable, as long as this comment remains intact.
  If you find this source useful, you may use this code in your own projects
  free of charge, but some acknowledgement to the author of this code is always
  appreciated :)
  The source is however distributed 'as is' without waranty and/or support, and
  may not be fit for each and every application.  Use it at your own discretion
  and at your own risk.
  The source already has undergone testing.  This doesn't mean however that all
  bugs are removed from this piece of code.  If you find one of them, please
  contact me about it.  I can however not guarantee when and if the bug will be
  fixed.

  More information about this module can be found in the accompanying HTML file.

*******************************************************************************/

#ifndef INCLUDE_TWOLOGS_COMMON_HIRESTIMER_H
#define INCLUDE_TWOLOGS_COMMON_HIRESTIMER_H

#include <windows.h>

// Possible timer states
enum class EHiResTimerState {
  eIdle,
  eStarted,
  eStopped
};

class CHiResTimer {
public:
  // Con- & destructor
  CHiResTimer(bool bAutoStart = false);
  virtual ~CHiResTimer();

  // Returns whether a hires timer is supported
  bool IsSupported() const;

  // Starts the hires timer
  void Start();

  // Stops the hires timer
  void Stop();

  // Resets the timer
  void Reset();

  // Gets the state of the timer
  EHiResTimerState GetState() const;

  // Gets the timed interval in seconds
  double GetInterval() const;

protected:
  // Our state
  EHiResTimerState m_eState;

  // Whether a timer is supported by the hardware
  bool m_bSupported;

  // The start- and stop times
  LARGE_INTEGER m_nStartTime;
  LARGE_INTEGER m_nStopTime;

  // The frequency of the timer
  LARGE_INTEGER m_nFrequency;
};

#endif // INCLUDE_TWOLOGS_COMMON_HIRESTIMER_H

HiResTimer.cpp

/*******************************************************************************

  Version: 1
  Author:  Carl Colijn, TwoLogs
  Contact: c.colijn@twologs.com
  Source:  http://www.twologs.com/sourcecode

  This code is freely distributable, as long as this comment remains intact.
  If you find this source useful, you may use this code in your own projects
  free of charge, but some acknowledgement to the author of this code is always
  appreciated :)
  The source is however distributed 'as is' without waranty and/or support, and
  may not be fit for each and every application.  Use it at your own discretion
  and at your own risk.
  The source already has undergone testing.  This doesn't mean however that all
  bugs are removed from this piece of code.  If you find one of them, please
  contact me about it.  I can however not guarantee when and if the bug will be
  fixed.

  More information about this module can be found in the accompanying HTML file.

*******************************************************************************/

#include "HiResTimer.h"

// Constructor
CHiResTimer::CHiResTimer(bool bAutoStart) {
  // Get the frequency of the timer and look if it is supported
  m_bSupported = QueryPerformanceFrequency(&m_nFrequency) != 0;
  m_bSupported &= (m_nFrequency.QuadPart != 0);

  // Make sure it is initialized
  Reset();

  // And start it, if needed
  if (bAutoStart) {
    Start();
  }
}

// Destructor
CHiResTimer::~CHiResTimer() {
}

// Returns whether a hires timer is supported
bool CHiResTimer::IsSupported() const {
  return m_bSupported;
}

// Starts the hires timer
void CHiResTimer::Start() {
  m_eState = EHiResTimerState::eStarted;
  QueryPerformanceCounter(&m_nStartTime);
}

// Stops the hires timer
void CHiResTimer::Stop() {
  QueryPerformanceCounter(&m_nStopTime);
  m_eState = EHiResTimerState::eStopped;
}

// Resets the timer
void CHiResTimer::Reset() {
  m_nStartTime.QuadPart = m_nStopTime.QuadPart = 0;
  m_eState = EHiResTimerState::eIdle;
}

// Gets the state of the timer
EHiResTimerState CHiResTimer::GetState() const {
  return m_eState;
}

// Gets the timed interval in seconds
double CHiResTimer::GetInterval() const {
  // Look if the timer has started
  double nInterval = 0.0;
  if (m_bSupported && m_eState != EHiResTimerState::eIdle) {
    // Yes -> look up to which time to measure
    LARGE_INTEGER nStopTime;
    if (m_eState == EHiResTimerState::eStopped) {
      nStopTime = m_nStopTime;
    } else {
      QueryPerformanceCounter(&nStopTime);
    }

    // And calculate the interval
    nInterval = (nStopTime.QuadPart - m_nStartTime.QuadPart) /
                (double)m_nFrequency.QuadPart;
  }

  // And return the interval
  return nInterval;
}