Module: qtimer.cpp

class QTimer
.h

constructorQTimer()
destructor~QTimer()
ResetBasevoid ResetBase()

Reset 0-base for time counting

UpdateTicksvoid UpdateTicks()

Updates 'ticks' to the last available time instant

Resetvoid Reset()
Startvoid Start()

Turn timer on

Stopvoid Stop()

Stop time recording

GetTimevoid GetTime(ulong *secs,ulong *micros)

/** Get passed time since last reset **/

GetSecondsulong GetSeconds()

/** Get passed seconds since last Start() **/

GetTicksuint64 GetTicks()

#else
int QTimer::GetTicks()
#endif
Get #ticks, 1 tick is 1 vertical blank interval, or nanosecond, or WHATEVER!
Don't use this function in application code; too many variant

GetMilliSecondsint GetMilliSeconds()
WaitForTimevoid WaitForTime(int secs,int msecs)

Reasonably multitasking-friendly wait for the timer to pass the given
time and return.
On O2's and most low level SGI's, the accurary is ~10ms (scheduler slice)
Starts the timer if it is not running (instead of just returning)
On Win32, we might just use Sleep()

AdjustMilliSecondsvoid AdjustMilliSeconds(int delta)

Adjust time in milliseconds
'delta' may be negative or positive. Note that this may underflow the
timer, meaning it will be negative.


Flat functions
 

mainvoid main(void)


/*
 * QTimer - Simple timing things
 * 11-08-94: Created! (from the Amiga!)
 * 01-04-99: Using VTraces for finer granularity
 * 10-05-99: Using UST for even more granularity (nanoseconds)
 * 03-03-01: Modified to use timeGetTime() on Win32; better resolution.
 * FUTURE:
 * - Optionally select (at construction time) what timing method to use
 * (for VTraces for example)
 * BUGS:
 * - GetTime() does not work
 * (C) MG/RVG
 */

#include <qlib/timer.h>
#include <qlib/app.h>
#include <time.h>
#include <qlib/debug.h>
DEBUG_ENABLE

// Vertical trace resolution?
//#define USE_VTRACE

#ifndef WIN32
// UST nanosecond resolution?
#define USE_UST
#endif

#ifdef WIN32
// time() usage? Bad resolution and misplaced offsets within the second
//#define USE_TIME

#define USE_OS_TICK
#endif

// Screen Hertz; for Quizes, PAL should do the trick
#define TRACES_PER_SECOND	50

QTimer::QTimer()
{ Reset();
}
QTimer::~QTimer()
{
}

void QTimer::ResetBase()
// Reset 0-base for time counting
{
#ifdef USE_VTRACE
  baseVCount=app->GetVTraceCount();
#endif
#ifdef USE_UST
  dmGetUST(&baseUST);
#endif
#ifdef USE_TIME
  time(&base_secs);
#endif
#ifdef USE_OS_TICK
  //baseTicks=(int)GetTickCount();
  baseTicks=(int)timeGetTime();
#endif
}

/**********************
* STOPWATCH EMULATION *
**********************/
void QTimer::UpdateTicks()
// Updates 'ticks' to the last available time instant
{
  if(!isRunning)
  { //qerr("QTimer::UpdateTicks() called without running timer");
    return;
  }
#ifdef USE_VTRACE
  int vc;
  vc=app->GetVTraceCount();
  ticks+=vc-baseVCount;
  baseVCount=vc;
#endif
#ifdef USE_UST
  uint64 vc;
  dmGetUST(&vc);
  ticks+=vc-baseUST;
  baseUST=vc;
#endif
#ifdef USE_OS_TICK
  // Looks a lot like UST
  int t;
  //t=(int)GetTickCount();
  t=(int)timeGetTime();
  ticks+=t-baseTicks;
  baseTicks=t;
#endif
}
void QTimer::Reset()
{ /** Starts timer at current time **/
  ResetBase();
  ticks=0;
  isRunning=FALSE;
}
void QTimer::Start()
// Turn timer on
{
  if(isRunning)return;
  ResetBase();
  isRunning=TRUE;
}
void QTimer::Stop()
// Stop time recording
{
  if(!isRunning)return;
  UpdateTicks();
  isRunning=FALSE;
}

/****************
* RETRIEVE TIME *
****************/
void QTimer::GetTime(ulong *secs,ulong *micros)
/** Get passed time since last reset **/
{
  qerr("QTimer::GetTime() called; is OBSOLETE");
}
ulong QTimer::GetSeconds()
/** Get passed seconds since last Start() **/
{ 
#ifdef USE_VTRACE
  long s;
  int  vc;
  //vc=app->GetVTraceCount();
  //return (ulong)((vc-baseVCount)/TRACES_PER_SECOND);
  UpdateTicks();
  return ticks/TRACES_PER_SECOND;
#endif
#ifdef USE_UST
  UpdateTicks();
  return ticks/1000000000;		// 10^9 = nanoseconds
#endif
#ifdef USE_TIME
  time_t t;
  time(&t);
  return (ulong)(t-base_secs);
#endif
#ifdef USE_OS_TICK
  UpdateTicks();
  return ticks/1000;
#endif
}
#ifdef USE_UST
uint64 QTimer::GetTicks()
#else
int QTimer::GetTicks()
#endif
// Get #ticks, 1 tick is 1 vertical blank interval, or nanosecond, or WHATEVER!
// Don't use this function in application code; too many variant
{
  UpdateTicks();
  return ticks;
  //int  vc;
  //vc=app->GetVTraceCount();
  //return (int)(vc-baseVCount);
}
int QTimer::GetMilliSeconds()
{
#ifdef USE_UST
  //uint64 div;
  //div=1000000;
  UpdateTicks();
//qdbg("ticks=%lld\n",ticks);
  return (int)(ticks/1000000);
#endif
#ifdef USE_TIME
  UpdateTicks();
  return (int)(ticks*1000);
#endif
#ifdef USE_OS_TICK
  UpdateTicks();
  return (int)ticks;
#endif
}

void QTimer::WaitForTime(int secs,int msecs)
// Reasonably multitasking-friendly wait for the timer to pass the given
// time and return.
// On O2's and most low level SGI's, the accurary is ~10ms (scheduler slice)
// Starts the timer if it is not running (instead of just returning)
// On Win32, we might just use Sleep()
{ int n;
  secs=secs*1000+msecs;
  // Make sure timer is running
  if(!IsRunning())Start();
  while(1)
  { n=GetMilliSeconds();
    if(n>=secs)break;
    QNap(1);
  }
}

/*****************
* TIME ADJUSTING *
*****************/
void QTimer::AdjustMilliSeconds(int delta)
// Adjust time in milliseconds
// 'delta' may be negative or positive. Note that this may underflow the
// timer, meaning it will be negative.
{
#ifdef USE_UST
  uint64 delta64;
  delta64=(uint64)delta;
  // Get time in nanoseconds
  delta64*=1000000;
  ticks+=delta64;
#endif
#ifdef USE_OS_TICK
  // Adjust msecs
  ticks+=delta;
#endif
}

/** TEST **/

//#define NOTDEF_TEST
#ifdef NOTDEF_TEST

#include <stdio.h>

void main(void)
{ QTimer *qt;
  ulong s,m;
  QAppSetup();
  qt=new QTimer();
  while(!RMB())
  { qt->GetTime(&s,&m);
    printf("S=%d, M=%4d\n",s,m);
  }
  //delete qt;
  QAppQuit();
}

#endif