wilbert wrote:
Glad you got it to work
A little remark on OS X ... mach_absolute_time() like you are using now is the best function to use since it is very fast.
The return value however is absolute time. On most systems this seems to be identical to nanoseconds but it is not guaranteed to be so.
To make sure you get nanoseconds, you can use a simple conversion function or convert it yourself
AbsoluteToNanoseconds from the CoreServices framework is the easy way.
The other (more low level) way is to get information using mach_timebase_info once and when you want to convert absolute time to nanoseconds, multiply by numer and divide by denom.
Since you want microseconds, the easiest way is maybe to add a double precision value to your timer structure for OS X that you initialize once and multiply by that like the example above.
Like this :
Code:
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; AUTOMATICALLY GENERATED CODE, DO NOT MODIFY
; UNLESS YOU REALLY, REALLY, REALLY MEAN IT !!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Code generated by : Dev-Type V3.139.671
; Project name : High Resolution Timer
; File name : HighResTimer.pb
; File Version : 1.1.0
; Programmation : OK
; Programmed by : Guimauve
; Creation Date : 04-03-2012
; Last update : 05-03-2012
; Coded for PureBasic V4.60
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Notes :
;
; This is a Windows, Linux and MacOS X compliant
; High Resolution Timer sustem.
;
; It's insperated from Timer Class found here :
; http://www.songho.ca/misc/timer/timer.html
;
; Additional Code
; - Wilbert (PureBasic English Forum)
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
#CLOCK_MONOTONIC = 1
Structure TimeSpec
Second.i
NanoSecond.l
EndStructure
Macro GetTimeSpecSecond(TimeSpecA)
TimeSpecA\Second
EndMacro
Macro GetTimeSpecNanoSecond(TimeSpecA)
TimeSpecA\NanoSecond
EndMacro
Macro ResetTimeSpec(TimeSpecA)
GetTimeSpecSecond(TimeSpecA) = 0
GetTimeSpecNanoSecond(TimeSpecA) = 0
EndMacro
ImportC "-lrt"
clock_gettime(ClockID.l, *TimeSpecA.TimeSpec)
EndImport
CompilerCase #PB_OS_MacOS
Structure TimeBase
Numerator.l
Denominator.l
EndStructure
Macro GetTimeBaseNumerator(TimeBaseA)
TimeBaseA\Numerator
EndMacro
Macro GetTimeBaseDenominator(TimeBaseA)
TimeBaseA\Denominator
EndMacro
Macro ResetTimeBase(TimeBaseA)
GetTimeBaseNumerator(TimeBaseA) = 0
GetTimeBaseDenominator(TimeBaseA) = 0
EndMacro
ImportC ""
mach_absolute_time.q()
mach_timebase_info(*TimeBaseA.TimeBase)
EndImport
CompilerEndSelect
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Structure declaration <<<<<
Structure HighResTimer
Stopped.b
StartMicroSec.q
StopMicroSec.q
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Frequency.q
StartCount.q
EndCount.q
CompilerCase #PB_OS_Linux
StartCount.TimeSpec
EndCount.TimeSpec
CompilerCase #PB_OS_MacOS
MicroSecConversion.d
TimeBase.TimeBase
StartCount.q
EndCount.q
CompilerEndSelect
EndStructure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The observators <<<<<
Macro GetHighResTimerStopped(HighResTimerA)
HighResTimerA\Stopped
EndMacro
Macro GetHighResTimerStartMicroSec(HighResTimerA)
HighResTimerA\StartMicroSec
EndMacro
Macro GetHighResTimerStopMicroSec(HighResTimerA)
HighResTimerA\StopMicroSec
EndMacro
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Macro GetHighResTimerFrequency(HighResTimerA)
HighResTimerA\Frequency
EndMacro
Macro GetHighResTimerStartCount(HighResTimerA)
HighResTimerA\StartCount
EndMacro
Macro GetHighResTimerEndCount(HighResTimerA)
HighResTimerA\EndCount
EndMacro
CompilerCase #PB_OS_Linux
Macro GetHighResTimerStartCount(HighResTimerA)
HighResTimerA\StartCount
EndMacro
Macro GetHighResTimerEndCount(HighResTimerA)
HighResTimerA\EndCount
EndMacro
CompilerCase #PB_OS_MacOS
Macro GetHighResTimerMicroSecConversion(HighResTimerA)
HighResTimerA\MicroSecConversion
EndMacro
Macro GetHighResTimerTimeBase(HighResTimerA)
HighResTimerA\TimeBase
EndMacro
Macro GetHighResTimerStartCount(HighResTimerA)
HighResTimerA\StartCount
EndMacro
Macro GetHighResTimerEndCount(HighResTimerA)
HighResTimerA\EndCount
EndMacro
CompilerEndSelect
; <<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The mutators <<<<<
Macro SetHighResTimerStopped(HighResTimerA, P_Stopped)
GetHighResTimerStopped(HighResTimerA) = P_Stopped
EndMacro
Macro SetHighResTimerStartMicroSec(HighResTimerA, P_StartMicroSec)
GetHighResTimerStartMicroSec(HighResTimerA) = P_StartMicroSec
EndMacro
Macro SetHighResTimerStopMicroSec(HighResTimerA, P_StopMicroSec)
GetHighResTimerStopMicroSec(HighResTimerA) = P_StopMicroSec
EndMacro
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Macro SetHighResTimerFrequency(HighResTimerA, P_Frequency)
GetHighResTimerFrequency(HighResTimerA) = P_Frequency
EndMacro
Macro SetHighResTimerStartCount(HighResTimerA, P_StartCount)
GetHighResTimerStartCount(HighResTimerA) = P_StartCount
EndMacro
Macro SetHighResTimerEndCount(HighResTimerA, P_EndCount)
GetHighResTimerEndCount(HighResTimerA) = P_EndCount
EndMacro
CompilerCase #PB_OS_Linux
Macro SetHighResTimerStartCount(HighResTimerA, P_StartCount)
CopyTimeSpec(P_StartCount, GetHighResTimerStartCount(HighResTimerA))
EndMacro
Macro SetHighResTimerEndCount(HighResTimerA, P_EndCount)
CopyTimeSpec(P_EndCount, GetHighResTimerEndCount(HighResTimerA))
EndMacro
CompilerCase #PB_OS_MacOS
Macro SetHighResTimerMicroSecConversion(HighResTimerA, P_MicroSecConversion)
GetHighResTimerMicroSecConversion(HighResTimerA) = P_MicroSecConversion
EndMacro
Macro SetHighResTimerTimeBase(HighResTimerA, P_TimeBase)
CopyMemory(P_TimeBase, GetHighResTimerTimeBase(HighResTimerA), SizeOf(TimeBase))
EndMacro
Macro SetHighResTimerStartCount(HighResTimerA, P_StartCount)
GetHighResTimerStartCount(HighResTimerA) = P_StartCount
EndMacro
Macro SetHighResTimerEndCount(HighResTimerA, P_EndCount)
GetHighResTimerEndCount(HighResTimerA) = P_EndCount
EndMacro
CompilerEndSelect
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Reset operator <<<<<
Macro ResetHighResTimer(HighResTimerA)
SetHighResTimerStopped(HighResTimerA, 0)
SetHighResTimerStartMicroSec(HighResTimerA, 0)
SetHighResTimerStopMicroSec(HighResTimerA, 0)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
SetHighResTimerFrequency(HighResTimerA, 0)
SetHighResTimerStartCount(HighResTimerA, 0)
SetHighResTimerEndCount(HighResTimerA, 0)
CompilerCase #PB_OS_Linux
ResetTimeSpec(GetHighResTimerStartCount(HighResTimerA))
ResetTimeSpec(GetHighResTimerEndCount(HighResTimerA))
CompilerCase #PB_OS_MacOS
SetHighResTimerMicroSecConversion(HighResTimerA, 0.0)
ResetTimeBase(GetHighResTimerTimeBase(HighResTimerA))
SetHighResTimerStartCount(HighResTimerA, 0)
SetHighResTimerEndCount(HighResTimerA, 0)
CompilerEndSelect
EndMacro
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code generated in : 00.010 seconds (17200.00 lines/second) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Macro HighResTimerElapsedMilliSec(HighResTimerA)
(HighResTimerElapsedMicroSec(HighResTimerA) * 0.001)
EndMacro
Macro HighResTimerElapsedSec(HighResTimerA)
(HighResTimerElapsedMicroSec(HighResTimerA) * 0.000001)
EndMacro
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Initialize operator <<<<<
Procedure InitializeHighResTimer(*HighResTimerA.HighResTimer)
ResetHighResTimer(*HighResTimerA)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
QueryPerformanceFrequency_(@GetHighResTimerFrequency(*HighResTimerA))
CompilerCase #PB_OS_MacOS
mach_timebase_info(@GetHighResTimerTimeBase(*HighResTimerA))
SetHighResTimerMicroSecConversion(*HighResTimerA, 1e-3 * GetTimeBaseNumerator(GetHighResTimerTimeBase(*HighResTimerA)) / GetTimeBaseDenominator(GetHighResTimerTimeBase(*HighResTimerA)))
CompilerEndSelect
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Start operator <<<<<
Procedure StartHighResTimer(*HighResTimerA.HighResTimer)
SetHighResTimerStopped(*HighResTimerA, #False)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
If GetHighResTimerFrequency(*HighResTimerA) = 0
InitializeHighResTimer(*HighResTimerA)
EndIf
QueryPerformanceCounter_(@GetHighResTimerStartCount(*HighResTimerA))
CompilerCase #PB_OS_Linux
clock_gettime(#CLOCK_MONOTONIC, @GetHighResTimerStartCount(*HighResTimerA))
CompilerCase #PB_OS_MacOS
If GetHighResTimerMicroSecConversion(*HighResTimerA) = 0.0
InitializeHighResTimer(*HighResTimerA)
EndIf
SetHighResTimerStartCount(*HighResTimerA, mach_absolute_time() * GetHighResTimerMicroSecConversion(*HighResTimerA))
CompilerEndSelect
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Stop operator <<<<<
Procedure StopHighResTimer(*HighResTimerA.HighResTimer)
SetHighResTimerStopped(*HighResTimerA, #True)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
QueryPerformanceCounter_(@GetHighResTimerEndCount(*HighResTimerA))
CompilerCase #PB_OS_Linux
clock_gettime(#CLOCK_MONOTONIC, @GetHighResTimerEndCount(*HighResTimerA))
CompilerCase #PB_OS_MacOS
SetHighResTimerEndCount(*HighResTimerA, mach_absolute_time() * GetHighResTimerMicroSecConversion(*HighResTimerA))
CompilerEndSelect
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The ElapsedMicroSec <<<<<
Procedure.q HighResTimerElapsedMicroSec(*HighResTimerA.HighResTimer)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
If GetHighResTimerStopped(*HighResTimerA) = #False
QueryPerformanceCounter_(@GetHighResTimerEndCount(*HighResTimerA))
EndIf
SetHighResTimerStartMicroSec(*HighResTimerA, GetHighResTimerStartCount(*HighResTimerA) * (1000000 / GetHighResTimerFrequency(*HighResTimerA)))
SetHighResTimerStopMicroSec(*HighResTimerA, GetHighResTimerEndCount(*HighResTimerA) * (1000000 / GetHighResTimerFrequency(*HighResTimerA)))
CompilerCase #PB_OS_Linux
If GetHighResTimerStopped(*HighResTimerA) = #False
clock_gettime(#CLOCK_MONOTONIC, @GetHighResTimerEndCount(*HighResTimerA))
EndIf
SetHighResTimerStartMicroSec(*HighResTimerA, GetTimeSpecSecond(GetHighResTimerStartCount(*HighResTimerA)) * 1000000 + GetTimeSpecNanoSecond(GetHighResTimerStartCount(*HighResTimerA)) / 1000)
SetHighResTimerStopMicroSec(*HighResTimerA, GetTimeSpecSecond(GetHighResTimerEndCount(*HighResTimerA)) * 1000000 + GetTimeSpecNanoSecond(GetHighResTimerEndCount(*HighResTimerA)) / 1000)
CompilerCase #PB_OS_MacOS
If GetHighResTimerStopped(*HighResTimerA) = #False
SetHighResTimerEndCount(*HighResTimerA, mach_absolute_time() * GetHighResTimerMicroSecConversion(*HighResTimerA))
EndIf
SetHighResTimerStartMicroSec(*HighResTimerA, GetHighResTimerStartCount(*HighResTimerA))
SetHighResTimerStopMicroSec(*HighResTimerA, GetHighResTimerEndCount(*HighResTimerA))
CompilerEndSelect
ProcedureReturn GetHighResTimerStopMicroSec(*HighResTimerA) - GetHighResTimerStartMicroSec(*HighResTimerA)
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< !!! WARNING - YOU ARE NOW IN A TESTING ZONE - WARNING !!! <<<<<
; <<<<< !!! WARNING - THIS CODE SHOULD BE COMMENTED - WARNING !!! <<<<<
; <<<<< !!! WARNING - BEFORE THE FINAL COMPILATION. - WARNING !!! <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
StartHighResTimer(HResTimer.HighResTimer)
Delay(1)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(5)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(499)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(500)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(1499)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(1501)
Debug HighResTimerElapsedMicroSec(HResTimer)
; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
I don't have a Mac so I can't test this code. I hope it work !
Best regards
Guimauve