Timer class overview

Measuring time

The Timer class can be used to time events. By default, a Timer class instance counts time in milliseconds since the first Timer class instantiation of the program. Access the current time with the getTime function which returns, by default, the number of milliseconds since the timer was set. There are 1000 milliseconds in a second, so 1000 milliseconds equals one second. Example 1 given below demonstrates how to access the current time. The example code below will print the numbers from 0 to 10 as the timer reaches 0, 1000, 2000, ... 10000 milliseconds.

Timer Example 1 full example

   stopwatch.reset();       // initialize timer to 0 millisec.
   
   while (counter <= 10) {
      if (stopwatch.getTime() > counter * 1000) {
         cout << counter << " " << flush;
         counter++;
      }
   }
   

Output:
     0 1 2 3 4 5 6 7 8 9 10
   

The time unit can be set to any arbitrary indivisible unit with the setTicksPerSecond function. Time units can be as small as the CPU clock speed, but are intended to be about the length of a millisecond or greater. For example, MIDI files have an arbitrary time unit described as ticks per second in the header to the file -- usually around 96 or so. A Timer object could match the timing units in this case by calling setTicksPerSecond(96) as shown in example 2 below.

Timer Example 2 full example

   stopwatch.reset();  
   stopwatch.setTicksPerSecond(96);  // 96 time units per second
   
   while (counter <= 10) {
      if (stopwatch.getTime() > counter * 96) {
         cout << counter << " " << flush;
         counter++;
      }
   }
   

Output:
     0 1 2 3 4 5 6 7 8 9 10
   

Warning: when changing the number of ticks per second with the setTicksPerSecond function, you should call the reset function at the same time. This will prevent a discontinuity which is created in the tick count when the timing resolution is changed.

There is another function called getTimerInSeconds which will return a floating-point value of the current time in seconds. Likewise, a function called getTimeInTicks is an analogous function which behaves in the exact same way as the getTime function. A generic way to count seconds with an arbitrary number of ticks per second is shown in example 3 below.

Timer Example 3 full example

   stopwatch.reset();  
   
   // set ticks rate between 100 and 999 ticks per second:
   stopwatch.setTicksPerSecond(rand() % 900 + 100);  
   
   while (counter <= 10) {
      if (stopwatch.getTime() > 
            counter*stopwatch.getTicksPerSecond()) {
         cout << counter << " " << flush;
         counter++;
      }
   }
   

Output:
     0 1 2 3 4 5 6 7 8 9 10
   


Timing dependency on CPU speed

The Timer class must have the correct speed for the CPU in order to give correct timing values. Since there is no direct way (at least known to me) of getting the CPU speed of the computer in a program, the Timer class will take a measurement of the CPU speed when the very first instance of the Timer class is created by calling the measureCpuSpeed function which takes about a 1/4 second to estimate the speed of the computer. The measured value is expected to be about +/- 5% of the correct value, but there is no guarentee to that since the measurement accuracy relies on many variables and assumptions.

If you want an accurate timer, then you must set the exact speed of your CPU with the setCpuSpeed function. For example, the function call Timer::setCpuSpeed(200000000) sets the CPU speed to 200 MHz. setCpuSpeed is a static function which can be called through an instance of the Timer class, or it can be called directly as shown in the previous sentence. Note that changing the CPU speed for one instance of the Timer class will change the value for all instances of the Timer class. You may view the Timer classes value for the CPU speed by calling the getCpuSpeed function. You can access the clock cycle count directly with the function clockCycles which will return the current number of clock cycles as a 64-bit integer since the computer was last rebooted.

Warning: The Timer class is only guarenteed to work on Pentium-class computers at the present time, since assembler code is used to access the clock cycle count from a Pentium hardware register in the function clockCycles. Assuming that the clockCycles function returns the proper value, all of the other class functions for the Timer class will work properly -- only the clockCycles function is OS/CPU dependent.



Coordinating timers

All timers are coordinated with each other until the reset function is called on one of them. Coordinated timers, when running at the same number of ticks per second, will output identical timing values. If you have two timers which you want to reset, yet still produce the exact same output, you would first reset one of the timers, then sync the two timers as shown in example 4.

Timer Example 4: synchronizing two timers  

   Timer timeA, timeB;

   // timeA and timeB output identical values.

   timeA.reset();

   // timeA and timeB no longer output identical values

   timeB.sync(timeA);

   // timeA and timeB now output identical values again.
   

Although calling the setTicksPerSecond function on each synchronized timer will cause them to output different numbers, the two timers are in fact still synchronized and will output identical values whenever they again have the same number of tick divisions per second. You can also reset both timers at nearly the same instant, but they would not be precisely coordinated with each other.



Periodic timing

The Timer class can also keep time in a cyclic manner which is often useful for music-related timing. There are two ways to specify the timing period of the timer:
  1. setPeriod -- this function will set the period length in terms of ticks. By default, the period is 1000.0 ticks, which is equal to one second using the default timing resolution of 1000 ticks per second. Note that the number of ticks in the period can be a floating-point number. A fractional position of into the tick time is allowable, since the actual resolution of the timer is in CPU clock cycles.
  2. setTempo -- the input to this function is a musical tempo marking. For example, if a quarter note equals 60 (MM = 60, which is one quarter note per second), then the period could be set by calling setTempo(60). Note that this function can also handle floating-point inputs.
The getPeriod function will return the current period duration that the timer is set to, which by default is 1000.0.

Now that a period is specified, it is best to rest the timer so that the start of the period is initialized. Once a periodic timer is started, you can call either the expired or the getPeriodCount functions to check on the period time:

  1. getPeriodCount -- returns the number of periods which the timer was last updated or reset. The returned value is an integer. For example, before one period duration has occured, the return value will be 0, between one and two period durations, the return value will be 1, and so on.
  2. expired -- behaves in a similar manner to getPeriodCount but will return the period count as a floating-point number. For example, half-way through the first period's duration, the return value with be 0.5.

Period timers can be updated by advancing the inital period pointer by an integral number of periods. This is useful to keep track of events which need to run once every period. Without updating a timer, the period count would continue to rise as each new period duration is arrived at. You can update a timer by two different methods, so that the period count cycles from 0 to 1 (or any other number of cycles):

  1. reset -- once the first period (for example) is reached, you could reset the timer, which would start counting periods from zero again. This method is only good if you want to have only an approximatly accurate period, since there will be a gradual shift in the period's absolute position.
  2. update -- this method of updating the period start position will exactly position the period counter at the next period position, unlike the reset function which will only approximately positon the period pointer by setting it to the current time. update called without arguments will update the period by one; giving an integer argument will update the period pointer by the specified number of periods.
An example use of updating is a bar, or measure, of music: updating at the beginning of each measure with result in a timer which keeps track of the current beat in the measure (update(4) for a 4/4 measure).


Implementation notes

Notes from the webpage http://www.sandpile.org/80x86/rdmsr.shtml:

So, an implementation in the C language to access the clock cycles on a Pentuim CPU using a UNIX operating system would be:

   unsigned long long int clockCount;
   __asm__ volatile (".byte 0x0f, 0x31" : "=A" (clockCount));

The same result from a Microsoft-base operating system:

   LONGLONG clockCount;
   unsigned long high_end, low_end;
   __asm {
      __asm _emit 0x0f __asm _emit 0x31
      mov high_end, edx
      mov low_end, eax
   }
   clockCount = high_end;
   clockCount = clockCount << 32;
   clockCount |= low_end;