Page 1 of 1

High resolution timer (windows x64 & x86)

Posted: Wed Feb 29, 2012 11:46 pm
by xorc1zt
Hi,

A high resolution timer library for purebasic written with C language.
The lib use the object system from purebasic (thanks to freak for the help).

link (18/03/2012): http://www.mediafire.com/?47a3t5v9h8pl877

first version: http://www.mediafire.com/?l669u97uxdd314v (x64 only)

readme.txt
usage:

to compile the lib you will need:

- windows sdk v7.1
- purebasic v4.60

start WinSDK Console (x64|x86).bat

to build and install the lib type nmake
to clean the folder type nmake clean

Don't forget to check the makefile for the names and paths

thanks to freak and Danilo for the help

-xorc1zt


functions :

GetTimeProcess( Resolution ) - Return the process elasped time.
GetTimeSys( Resolution ) - Return the system elasped time.
GetTimeDelta( Resolution ) - Return the elasped time since the previous call

CreateTimer( ID [, Time [, Resolution]] ) - Create a new timer ( Default resolution is millisecond )
FreeTimer( ID ) - Delete the timer
IsTimer( ID ) - Verifiy if ID is a timer object

ExamineTimers() - Update the timers

TimerSetInterval( ID, Time, Resolution ) - Set the interval time
TimerSetCallback( ID, FunctionAddress ) - Set the callback function

TimerGetStatus( ID ) - Return the status of timer
TimerGetInterval( ID ) - Return the interval time of the timer
TimerGetResolution( ID ) - Return the resolution of the timer

resolutions :

#PB_TIME_SECOND = 1
#PB_TIME_DECISECOND = 2
#PB_TIME_CENTISECOND = 3
#PB_TIME_MILLISECOND = 4
#PB_TIME_MICROSECOND = 5
#PB_TIME_NANOSECOND = 6

timer status :

#PB_TIMERSTATUS_WAIT = 1
#PB_TIMERSTATUS_RING = 2

Re: High resolution timer (windows x64)

Posted: Sat Mar 03, 2012 10:04 pm
by Falko
Thank you :wink:

Re: High resolution timer (windows x64)

Posted: Tue Mar 06, 2012 4:09 am
by Zach
I'd been wondering about high resolution timers and what was available out of the box..

Although I had to say, it seems a bit involved to get this installed, and being 64-bit is kind of.... well :|

That being said.. Is there any way to simply package it into a DLL, and if so any plans? What about for 32-bit systems? (I develop on x64 but I compile for x32)

Re: High resolution timer (windows x64)

Posted: Tue Mar 06, 2012 12:25 pm
by Danilo
Thanks xorc1zt!

I tried to change some things to get it to work with 32bit too.
Looks like it works, but i am not sure about it yet. I am sleepy now. :D

Can you check if my modifications are correct, please? I changed calling conventions,
makefile, .desc file, ...
Could easily be that it is incorrect and a mess now, but maybe you get some ideas on how to compile it also for x86. ;)
It needs to be checked and tested by somebody for sure.

I also included 2 compiled PB-Libs in UserLibraries\x64 and \x86, so everybody can test it.

Download: PBTime_DaniloMod.zip

BTW: What is the right Name for PB's Integer (.i) in UserLib .desc files? It does not like 'Int' nor 'Integer',
could it be that Long is 32/64 bit depending on platform?

Re: High resolution timer (windows x64)

Posted: Tue Mar 06, 2012 8:38 pm
by xorc1zt
good work

about the desc file. you must use long with x86 or quad with x64. there is no integer type. a good way to handle both is to use the preprocessor

Code: Select all

CompilerIf X86
   Function, Long, (*pointer) - xxxxxxx
   Long | CDecl
CompilerElse
   Function, Quad, (*pointer) - xxxxxxx
   Quad | CDecl
CompilerEndIf
then execute LibraryMaker.exe with the argument "/CONSTANT X86" for 32 bits or nothing for 64 bits.

about the calling convention. there are no stdcall or cdecl with the 64 bits platform, i think the LibraryMaker ignore those flags if you link on x64 but i still put the cdecl flag for x86. if you want to switch between stdcall or cdecl you can use the compiler flag "/Gz"

Re: High resolution timer (windows x64)

Posted: Tue Mar 06, 2012 8:51 pm
by Danilo
xorc1zt wrote:about the desc file. you must use long with x86 or quad with x64. there is no integer type. a good way to handle both is to use the preprocessor
OK, thank you! So my modification is incorrect for sure. What a mess, why is there no Integer type for .desc? Now you have to write everything 2 times...
by using CompilerIf or write 2 .desc files.

Are you going to make a x86 version of your lib?

And a little request - could you make:
- CreateTimer( ID) ; empty timer
- CreateTimer( ID, FunctionAddress, Time ) ; timer with callback and Time as milliseconds (as usual)
- CreateTimer( ID, FunctionAddress, Time, Resolution ) ; full timer

Correct description would be:
CreateTimer( ID [, FunctionAddress, Time [, Resolution ]] )

So it is not always required to call CreateTimer, TimerSetCallback, TimerSetInterval.
I think you use this combination most of the time...?

Re: High resolution timer (windows x64)

Posted: Wed Mar 07, 2012 2:50 am
by xorc1zt
update

- x86 support
- added the optional parameters for CreateTimer()

http://www.mediafire.com/?47a3t5v9h8pl877

edit: about the time variable. the type must be quad or integer on x64 but only quad on x86

Code: Select all

define curtime.i = GetTimeSys( #PB_TIME_NANOSECOND ) ; good on x64, wrong on x86
define curtime.q = GetTimeSys( #PB_TIME_NANOSECOND ) ; good on x64 and x86
purebasic should allow definition of new type like typedef with C, a workaround is to use the macro keyword

Code: Select all

macro PBTIME_T
    q
EndMacro

define curTime.PBTIME_T = GetTimeSys( #PB_TIME_NANOSECOND )
debug curTime

Re: High resolution timer (windows x64)

Posted: Wed Mar 07, 2012 10:08 am
by Danilo
xorc1zt wrote:update

- x86 support
- added the optional parameters for CreateTimer()
Thanks xorc1zt, works now in both modes, x86 and x64.

"CreateTimer(1,200)" gives a linker error, but it is just a spelling mistake
in 'CreateTimer.c': PB_CreateTime2() is missing the second 'r'. Works after correction.

Re: High resolution timer (windows x64 & x86)

Posted: Tue Mar 27, 2012 3:24 am
by xorc1zt
same kind of timers which rely on GetSystemTimeAsFileTime

Code: Select all

; Timer
; xorc1zt
; 2012

;* ----------------------------------------------
;* NAME: GetSystemTimeAsFileTime
;*
;* DECLARATION: void WINAPI GetSystemTimeAsFileTime(
;*              __out  LPFILETIME lpSystemTimeAsFileTime
;*              );
;*
;* DEFENITION: lpSystemTimeAsFileTime get a 64-bit value 
;*             representing the number of 100-nanosecond
;*             intervals since January 1, 1601 (UTC).
;*
;* RETURN VALUE: None
;*
;* NOTE: accuracy is crappy on Windows XP
;* ----------------------------------------------

#SECOND         = 10000000
#DECISECOND     = 1000000
#CENTISECOND    = 100000
#MILLISECOND    = 10000

#STATUS_WAIT    = 1
#STATUS_RING    = 2

Prototype callbackPROTO()

structure PB_TIMER
    handle.i
    timeOut.q
    timeInterval.q
    status.i
    callback.callbackPROTO
EndStructure

global NewList timerList.PB_TIMER()

procedure.q GetSystemFileTime()
    define curTime.q
    GetSystemTimeAsFileTime_(@curTime)
    ProcedureReturn curTime
EndProcedure

procedure.i NewTimer( interval.q )
    LastElement( timerList() )
    AddElement( timerList() )
    timerList()\handle          = @timerList()
    timerList()\status          = #STATUS_WAIT
    timerList()\timeInterval    = interval
    timerList()\timeOut         = GetSystemFileTime() + interval
    
    ProcedureReturn timerList()\handle
EndProcedure

procedure.b DelTimer( handle.i )
    ChangeCurrentElement( timerList(), handle )
    
    if not ( timerList()\handle = handle )
        ProcedureReturn #False
    endif
    
    timerList()\handle = 0
    
    DeleteElement( timerList() )
    
    ProcedureReturn #True
EndProcedure

procedure UpdateTimer()
    define curTime,q
    
    curTime = GetSystemFileTime()
    
    ForEach timerList()
        if ( timerList()\status = 0 )
            continue
        ElseIf ( timerList()\status = #STATUS_RING )
            timerList()\status  = #STATUS_WAIT
            continue
        ElseIf ( curTime > timerList()\timeOut )
            timerList()\status  = #STATUS_RING
            timerList()\timeOut = curTime + timerList()\timeInterval
            
            if timerList()\callback
                timerList()\callback()
            endif
            continue
        endif
    Next
EndProcedure

procedure.i GetTimerStatus( handle.i )  
    ChangeCurrentElement( timerList(), handle )
    
    if not ( timerList()\handle = handle )
        ProcedureReturn #False
    endif     
    
    ProcedureReturn timerList()\status
EndProcedure



; ***************
; TEST
; ***************

define counter.i    = 0
define time.q       = GetSystemFileTime()
define test.i       = newTimer( #SECOND )
define test2.i      = NewTimer( 500 * #MILLISECOND )


time + ( #SECOND * 10 )

debug "10 sec loop"

Repeat
    updateTimer()
    
    if ( GetTimerStatus( test ) = #STATUS_RING )
        debug "Hi - 1 sec"
    endif
    
    if ( GetTimerStatus( test2 ) = #STATUS_RING )
        debug "Hi - 500 ms"
        counter + 1
    endif
    
    if counter = 5
        DelTimer( test2 )
        debug "500 ms timer is no more !!!"
        counter + 1
    endif
until GetSystemFileTime()> time