Danilo's PBOSL Hi-res Timer as PB source include

Share your advanced PureBasic knowledge/code with the community.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Danilo's PBOSL Hi-res Timer as PB source include

Post by netmaestro »

I hope Danilo won't mind this, but srod did the same with the ToolBarPro library some months ago and he hasn't been assassinated afaik. Libs written in C have the drawback of only being usable in compiled form and at the rate the team is releasing new versions of PB, compiled userlibs have a shelf life of about 3 months.

I'm not sure why the timeBeginPeriod code is there, I can't see the need for it as TimeSetEvent covers all that ground but he's got it in there and this is a faithful translation so in it stays.

Code: Select all

;===============================================================================
; Program:          PBOSL_Timer Clone
; Author:           Lloyd Gallant (netmaestro) based on work by Danilo Krahn 
; Date:             November 26, 2007
; Target Compiler:  PureBasic 4.0 and later
; Target OS:        Windows XP/Vista 
; License:          Free, unrestricted, no warranties expressed or implied
;
; This code was originally conceived and written in C by Danilo Krahn
; and released as part of the PureBasic Open Source Libraries collection.
; Its functions are reproduced here in PureBasic sourcecode for use
; as a PB Include file for those who prefer not to use compiled libraries in 
; their projects. All functions in this library are fully compatible in name
; and functionality with those in the compiled PBOSL version.
;
; If you have programs that use the compiled PBOSL_Timer library and you would 
; prefer a .pbi include alternative, you may safely include this file in your
; projects and all the hi-res timer functions will work as expected.
; (that's an opinion, not a warranty)
;
;===============================================================================

Global timer_res.TIMECAPS
Global Dim timer_handles(16)
Global Dim timer_procedures(16)

timeGetDevCaps_( timer_res, SizeOf(TIMECAPS) )

Procedure Timer_Init()
  timeBeginPeriod_( timer_res\wPeriodMin )
  For i=1 To 16
    timer_handles(i)    = 0
    timer_procedures(i) = 0
  Next
EndProcedure

Procedure GetMinTimerResolution()
  ProcedureReturn timer_res\wPeriodMin
EndProcedure

Procedure GetMaxTimerResolution()
  ProcedureReturn timer_res\wPeriodMax
EndProcedure

Procedure Timer_CallBack( timer_handle, msg, timer_number, dw1, dw2)
  If timer_procedures(timer_number)
    CallFunctionFast( timer_procedures(timer_number) )
  EndIf
EndProcedure

Procedure StartTimer( timer_number, delay, *timer_proc_address )
  If timer_number > 15
    ProcedureReturn 0
  EndIf
  If timer_handles(timer_number)
    timeKillEvent_( timer_handles(timer_number) )
  EndIf
  timer_procedures(timer_number) = *timer_proc_address
  timer_handles(timer_number) = timeSetEvent_( delay, 0, @Timer_CallBack(), timer_number, #TIME_PERIODIC )
  ProcedureReturn timer_handles(timer_number)
EndProcedure

Procedure EndTimer( timer_number )
  If timer_number > 15
    ProcedureReturn 0
  EndIf
  If timer_handles(timer_number)
    timeKillEvent_( timer_handles(timer_number) )
    ProcedureReturn 1
  EndIf
  ProcedureReturn 0
EndProcedure

Procedure Timer_End()
  For i=1 To 16
    If timer_handles(i)
      timeKillEvent_(timer_handles(i))
    EndIf
  Next
  timeEndPeriod_( timer_res\wPeriodMin )
EndProcedure
BERESHEIT
User avatar
IceSoft
Addict
Addict
Posts: 1695
Joined: Thu Jun 24, 2004 8:51 am
Location: Germany

Post by IceSoft »

See what MSDN says:

Code: Select all

timeBeginPeriod
The timeBeginPeriod function sets the minimum timer resolution for an application or device driver. 

MMRESULT timeBeginPeriod(
  UINT uPeriod  
);
Parameters

uPeriod

Minimum timer resolution, in milliseconds, for the application or device driver.

Return Values

Returns TIMERR_NOERROR if successful or TIMERR_NOCANDO if the resolution specified in uPeriod is out of range. 

Remarks

Call this function immediately before using timer services, and call the timeEndPeriod function immediately after you are finished using the timer services.

You must match each call to timeBeginPeriod with a call to timeEndPeriod, specifying the same minimum resolution in both calls. An application can make multiple timeBeginPeriod calls as long as each call is matched with a call to timeEndPeriod.
Belive! C++ version of Puzzle of Mystralia
Bug Planet
<Wrapper>4PB, PB<game>, =QONK=, PetriDish, Movie2Image, PictureManager,...
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

TimeSetEvent doesn't need it.
BERESHEIT
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

here is my old translation on the german board
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I can't speak German so I don't get to the German board much, but thanks for posting that. If I'd known it existed I wouldn't have written mine.

On the timeBeginPeriod subject, if it were required for TimeSetEvent then this code would be debugging a value much smaller than 1000 but here it's debugging exactly 1000 every time:

Code: Select all

Global x=0

Procedure Test(uID, uMsg, dwUser, dw1, dw2)
  x+1
EndProcedure

TEvent = timeSetEvent_(1,0,@Test(),0,#TIME_PERIODIC)

Delay (1000) ; Allow 1 second for the timer proc to increment x

timeKillEvent_(TEvent)

Debug x
BERESHEIT
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Sorry, but as long as i know Danilo and you are wrong.
MS does not recognize that stuff as "HI-RES timing", but just as "Multimedia timing".
"HI-RES timing" belongs to other different Winapi stuff.

HI-RES timers are usually below 1 millisecond for PCs since about year 2000 until now.

When a user search for hi-res timers in this forum he will be led up to a wrong info due to threads like this. :?
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Yeah! QueryPerformanceCounter_() if I remember correctly is a HI-RES timer.

As to timeBeginPeriod_() and timeEndPeriod_() they may not be needed for setEvent etc. But they are needed (at least on XP, not sure on Vista) to get close to 1ms when using Delay() or Sleep_() otherwise you get only as fine grained as 10ms or such. Win 9x has 1ms by default though.
ElapsedMilliseconds() is not as accurate as timeGetTime_()

Vista is supposedly normalizing all timers to all use HI-RES timers "under the hood" but only on hardware that actually provides a good HI-RES timer crystal etc.

In summary, timing on Windows is a pain in the ass :P
Post Reply