High resolution timer (windows x64 & x86)

Developed or developing a new product in PureBasic? Tell the world about it.
xorc1zt
Enthusiast
Enthusiast
Posts: 276
Joined: Sat Jul 09, 2011 7:57 am

High resolution timer (windows x64 & x86)

Post 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
Last edited by xorc1zt on Sun Mar 18, 2012 8:17 am, edited 6 times in total.
User avatar
Falko
Enthusiast
Enthusiast
Posts: 271
Joined: Sat Oct 04, 2003 12:57 pm
Location: Germany
Contact:

Re: High resolution timer (windows x64)

Post by Falko »

Thank you :wink:
www.falko-pure.de
Win11 Pro 64-Bit, PB_6.11b1
Zach
Addict
Addict
Posts: 1676
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: High resolution timer (windows x64)

Post 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)
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: High resolution timer (windows x64)

Post 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?
xorc1zt
Enthusiast
Enthusiast
Posts: 276
Joined: Sat Jul 09, 2011 7:57 am

Re: High resolution timer (windows x64)

Post 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"
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: High resolution timer (windows x64)

Post 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...?
xorc1zt
Enthusiast
Enthusiast
Posts: 276
Joined: Sat Jul 09, 2011 7:57 am

Re: High resolution timer (windows x64)

Post 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
Last edited by xorc1zt on Sun Mar 18, 2012 8:16 am, edited 1 time in total.
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: High resolution timer (windows x64)

Post 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.
xorc1zt
Enthusiast
Enthusiast
Posts: 276
Joined: Sat Jul 09, 2011 7:57 am

Re: High resolution timer (windows x64 & x86)

Post 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
Post Reply