Listing 2: clock.cpp.
// clock.cpp Begin
#include <clock.hpp>
#ifdef __PALMOS
inline clock_t clock();
#elif defined ( __WINDOWS )
inline clock_t clock();
#endif
clock_t cClock::_mClockStart = 0;
clock_t cClock::_mNumClockCalls = 0;
clock_t cClock::_mDesClockRes = 0;
clock_t cClock::_mDesClocksPerSec = 0;
clock_t cClock::_mNatClockRes = 0;
clock_t cClock::_mCalPeriod = 0;
clock_t cClock::_mCalCorrection = 0;
cClock::cClock( clock_t ClocksPerSec )
{
if ( !_mNumClockCalls )
{ // First time through so initialize
InitClock();
SetClockRes( ClocksPerSec );
}
}
cClock::cClock( clock_t CalPeriod, clock_t CalCorrection,
clock_t ClocksPerSec )
{
this->cClock::cClock( ClocksPerSec );
_mCalPeriod = CalPeriod;
_mCalCorrection = CalCorrection;
}
clock_t cClock::StartClock()
{
_mClockStart = 0;
_mClockStart = GetClock();
return ( _mClockStart );
}
clock_t cClock::GetClock()
{
clock_t Clock1, Clock2 = 0, NumCalls = 0;
Clock1 = clock();
if ( _mDesClockRes < _mNatClockRes )
{ // Use number of clock calls to get finer resolution
Clock2 = LoopClock( Clock1, &NumCalls );
if ( NumCalls < _mNumClockCalls )
{ // Get fraction of clock tick res that had transpired
Clock2 = _mNumClockCalls - NumCalls;
Clock2 *= _mNatClockRes;
if ( _mDesClocksPerSec > CLOCKS_PER_SEC )
{ // Covnert clock value to designated units
Clock2 *= _mDesClocksPerSec / CLOCKS_PER_SEC;
}
Clock2 /= _mNumClockCalls;
}
else
{ // clock had just ticked
Clock2 = 0;
}
}
if ( _mDesClocksPerSec > CLOCKS_PER_SEC )
{ // Covnert clock value to designated units
Clock1 *= _mDesClocksPerSec / CLOCKS_PER_SEC;
}
Clock2 += Clock1;
if ( _mDesClocksPerSec < CLOCKS_PER_SEC )
{ // Covnert clock value to designated units
Clock2 = RoundToRes( Clock2 );
}
Clock2 -= _mClockStart; // Get time from start
return ( Clock2 );
}
clock_t cClock::GetCalClock()
{
clock_t Clock = GetClock();
if ( _mCalPeriod && _mClockStart )
{ // Adjust time by the calibration correction
Clock += ( ( _mCalCorrection * Clock ) / _mCalPeriod );
}
return ( Clock );
}
clock_t cClock::GetClocksPerSec()
{
return ( _mDesClocksPerSec );
}
void cClock::SetCalibration( clock_t CalPeriod,
clock_t CalCorrection )
{
_mCalPeriod = CalPeriod;
_mCalCorrection = CalCorrection;
}
void cClock::CalcCalibration( clock_t ActualTime,
clock_t MeasuredTime, clock_t Correction )
{
clock_t Error = ActualTime - MeasuredTime;
clock_t Periods = Error / Correction;
_mCalPeriod = 0;
if ( Periods != 0 )
{
_mCalPeriod = MeasuredTime / Periods;
_mCalCorrection = Correction;
}
}
void cClock::InitClock()
{
clock_t Clock1, Clock2, Clock3;
clock_t Dummy = 0, NumCalls1 = 0, NumCalls2 = 0;
Clock1 = clock();
Clock2 = LoopClock( Clock1, &Dummy ); // Make clock tick
Clock3 = LoopClock( Clock2, &NumCalls1 );
Clock1 = LoopClock( Clock3, &NumCalls2 );
// Average two clock ticks
_mNumClockCalls = ( NumCalls1 + NumCalls2 ) / 2;
_mNatClockRes = ( Clock1 - Clock2 ) / 2;
}
clock_t cClock::LoopClock( clock_t Clock1, clock_t *NumCalls )
{
clock_t Clock2;
do
{ // Call the clock function till it updates (or ticks)
(*NumCalls)++; // Count the number of times called
Clock2 = clock();
}
while ( Clock2 == Clock1 );
return ( Clock2 );
}
void cClock::SetClockRes( clock_t ClocksPerSec )
{
if ( !ClocksPerSec )
{ // Set the designated units to the native value
_mDesClocksPerSec = CLOCKS_PER_SEC;
}
else
{
_mDesClocksPerSec = ClocksPerSec;
}
// Calculate the designated resolution
// A 0 value means the designated units are finer then the native units
_mDesClockRes = CLOCKS_PER_SEC / _mDesClocksPerSec;
}
clock_t cClock::RoundToRes( clock_t Clock )
{
clock_t Remainder =
Clock % ( CLOCKS_PER_SEC / _mDesClocksPerSec );
Clock = ( Clock * _mDesClocksPerSec ) / CLOCKS_PER_SEC;
if ( Remainder >= 5 )
{ // Round the time up by one
Clock++;
}
return ( Clock );
}
#ifdef __PALMOS
inline clock_t clock()
{
return ( (clock_t)TimGetTicks() );
}
#elif defined( __WINDOWS )
inline clock_t clock()
{
return ( (clock_t)GetTickCount() );
}
#endif
// clock.cpp End