PDA

View Full Version : Converting cross-platform C++ timer code to pascal...



paul_nicholls
15-08-2011, 06:30 AM
Hi all,
I found this page today:
http://www.songho.ca/misc/timer/timer.html

and I want to convert it over to pascal so I can have a high-resolution timer that works in Delphi and Freepascal :)

Any ideas how I can go about converting it the non-Delphi part? I am not sure what FPC units I would need for the time of day stuff - they use time.h...

cheers,
Paul

paul_nicholls
15-08-2011, 06:57 AM
This is my conversion attempt, but I'm sure it won't compile under Linux/Mac OSX as I don't know the correct units to include for those platforms:



unit xeEngine_timer;

interface

{$I xeEngine_include.inc}

procedure Timer_Init; cdecl; // initialize timer (like constructor)
procedure Timer_Start; cdecl; // start timer
procedure Timer_Stop; cdecl; // stop the timer
function Timer_GetElapsedTime: Double; cdecl; // get elapsed time in second
function Timer_GetElapsedTime_Sec: Double; cdecl; // get elapsed time in second (same as getElapsedTime)
function Timer_GetElapsedTime_mSec: Double; cdecl; // get elapsed time in milli-second
function Timer_GetElapsedTime_uSec: Double; cdecl; // get elapsed time in micro-second

implementation

uses
{$ifdef windows}
windows
{$endif}
;

var
startTimeInMicroSec : Double; // starting time in micro-second
endTimeInMicroSec : Double; // ending time in micro-second
stopped : Boolean; // stop flag
{$ifdef windows}
frequency : Int64; // ticks per second
startCount : Int64; //
endCount : Int64; //
{$else}
startCount : timeval; //
endCount : timeval //
{$endif}

procedure Timer_Init;
begin
{$ifdef windows}
QueryPerformanceFrequency(frequency);
startCount := 0;
endCount := 0;
{$else}
startCount.tv_sec := 0;
startCount.tv_usec := 0;
endCount.tv_sec := 0;
endCount.tv_usec := 0;
{$endif}

stopped := False;
startTimeInMicroSec := 0;
endTimeInMicroSec := 0;
end;

procedure Timer_Start;
begin
stopped := False; // reset stop flag
{$ifdef windows}
QueryPerformanceCounter(startCount);
{$else}
gettimeofday(startCount, nil);
{$endif}
end;

procedure Timer_Stop;
begin
stopped := True; // set timer stopped flag

{$ifdef windows}
QueryPerformanceCounter(endCount);
{$else}
gettimeofday(endCount, NULL);
{$endif}
end;

function Timer_GetElapsedTime: Double;
begin
Result := Timer_GetElapsedTime_Sec;
end;

function Timer_GetElapsedTime_Sec: Double;
begin
Result := Timer_GetElapsedTime_uSec * 0.000001;
end;

function Timer_GetElapsedTime_mSec: Double;
begin
Result := Timer_GetElapsedTime_uSec * 0.001;
end;

function Timer_GetElapsedTime_uSec: Double;
begin
{$ifdef windows}
if not stopped then
QueryPerformanceCounter(endCount);

startTimeInMicroSec := startCount * (1000000.0 / frequency);
endTimeInMicroSec := endCount * (1000000.0 / frequency);
{$else}
if not stopped then
gettimeofday(endCount, nil);

startTimeInMicroSec := (startCount.tv_sec * 1000000.0) + startCount.tv_usec;
endTimeInMicroSec := (endCount.tv_sec * 1000000.0) + endCount.tv_usec;
{$endif}

Result := endTimeInMicroSec - startTimeInMicroSec;
end;

end.

What do you guys/gals think?

cheers,
Paul

Andru
15-08-2011, 12:13 PM
gettimeofday

Will not work with FreePascal. You should use fpGetTimeOfDay instead, and unit Unix.

phibermon
15-08-2011, 07:33 PM
you may want to wrap it up in a class or put the timer vars in a record that you can pass to the functions to allow multiple timers.

paul_nicholls
15-08-2011, 08:36 PM
@Andru: thanks mate, that sort of information was what I was hoping for :)
@philbermon: I think I will go the record route, thanks for the idea!

cheers,
Paul

Carver413
15-08-2011, 09:12 PM
The X window system I am working on has a 3 stage timer built into the TApplication. it is a stak based timer adding timers is as easy as


Application.AddMsTask('OnTimer',Window,@OnTimer,10 );
Application.AddSecTask('OnTimer',Window,@OnTimer,1 3);
Application.AddMinTask('OnTimer',Window,@OnTimer,2 2);

the Ontimer is the event handling code and if it return's a True the event will remove itself.
to test it I opened 12 windows with a rotationing object in each. it seems to work very well as long as the load can be handled. I've only tested the AddMsTask so far but I see no reason why the others shouldn't work as expected. My system is built around a very custom linked list design. that allows for managing many lists from a single object. so it made since to build the timer functions into the application rather then creating a bunch of timer objects. this way all events are processed in a single loop including all of the X events.

code_glitch
15-08-2011, 09:44 PM
Turns out that Andru's right as always. Seems like his soltuion works for me on a Ubuntu 10.10 x64 Box with fpc 2.4.0 (ppcx64) if anyone is after the technicalities. Good find though.

Carver413
15-08-2011, 09:54 PM
I believe the correct unit is SysUtils as this has crossplatform support.
http://www.freepascal.org/docs-html/rtl/sysutils/index.html