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:  https://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 THiResTimerState {
  idle,
  started,
  stopped
};

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

  // 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
  THiResTimerState GetState() const;

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

protected:
  // Our state
  THiResTimerState m_state;

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

  // The start- and stop times
  LARGE_INTEGER m_startTime;
  LARGE_INTEGER m_stopTime;

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

#endif // INCLUDE_TWOLOGS_COMMON_HIRESTIMER_H

HiResTimer.cpp

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

  Version: 1
  Author:  Carl Colijn, TwoLogs
  Contact: c.colijn@twologs.com
  Source:  https://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
THiResTimer::THiResTimer(bool autoStart) {
  // Get the frequency of the timer and look if it is supported
  m_supported = QueryPerformanceFrequency(&m_frequency) != 0;
  m_supported &= (m_frequency.QuadPart != 0);

  // Make sure it is initialized
  Reset();

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

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

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

// Starts the hires timer
void THiResTimer::Start() {
  m_state = THiResTimerState::started;
  QueryPerformanceCounter(&m_startTime);
}

// Stops the hires timer
void THiResTimer::Stop() {
  QueryPerformanceCounter(&m_stopTime);
  m_state = THiResTimerState::stopped;
}

// Resets the timer
void THiResTimer::Reset() {
  m_startTime.QuadPart = m_stopTime.QuadPart = 0;
  m_state = THiResTimerState::idle;
}

// Gets the state of the timer
THiResTimerState THiResTimer::GetState() const {
  return m_state;
}

// Gets the timed interval in seconds
double THiResTimer::GetInterval() const {
  // Look if the timer has started
  double interval = 0.0;
  if (m_supported && m_state != THiResTimerState::idle) {
    // Yes -> look up to which time to measure
    LARGE_INTEGER stopTime;
    if (m_state == THiResTimerState::stopped) {
      stopTime = m_stopTime;
    } else {
      QueryPerformanceCounter(&stopTime);
    }

    // And calculate the interval
    interval =
      (stopTime.QuadPart - m_startTime.QuadPart) /
      (double)m_frequency.QuadPart;
  }

  // And return the interval
  return interval;
}