timer.bmx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. SuperStrict
  2. Rem
  3. bbdoc: Events/Timers
  4. End Rem
  5. Module BRL.Timer
  6. ModuleInfo "Version: 1.04"
  7. ModuleInfo "Author: Simon Armstrong, Mark Sibly, Bruce A Henderson"
  8. ModuleInfo "License: zlib/libpng"
  9. ModuleInfo "Copyright: Blitz Research Ltd"
  10. ModuleInfo "History: 1.04"
  11. ModuleInfo "History: New factory-based timer implementation."
  12. ModuleInfo "History: 1.03"
  13. ModuleInfo "History: Update to use Byte Ptr instead of int."
  14. Import BRL.Event
  15. Import pub.stdc
  16. Rem
  17. History:
  18. Removed use of _cycle:TTimer field to keep timer's alive - didn't work with 'real' GC!
  19. Replaced with BBRETAIN/BBRELEASE in C code.
  20. Added check for OS timer creation failure
  21. Added check for Win32 timer firing after timeKillEvent
  22. Removed brl.standardio dependancy
  23. End Rem
  24. Type TTimer Abstract
  25. Method Ticks:Int() Abstract
  26. Method Stop() Abstract
  27. Method Fire() Abstract
  28. Method Wait:Int() Abstract
  29. Function Create:TTimer( hertz:Float,event:TEvent=Null ) Abstract
  30. End Type
  31. Rem
  32. bbdoc: Create a timer
  33. returns: A new timer object
  34. about:
  35. #CreateTimer creates a timer object that 'ticks' @hertz times per second.
  36. Each time the timer ticks, @event will be emitted using #EmitEvent.
  37. If @event is Null, an event with an @id equal to EVENT_TIMERTICK and
  38. @source equal to the timer object will be emitted instead.
  39. End Rem
  40. Function CreateTimer:TTimer( hertz:Float,event:TEvent=Null )
  41. If timer_factories Then
  42. Return timer_factories.Create(hertz, event)
  43. Else
  44. Throw "No Timer installed. Maybe Import BRL.TimerDefault ?"
  45. End If
  46. End Function
  47. Rem
  48. bbdoc: Get timer tick counter
  49. returns: The number of times @timer has ticked over
  50. End Rem
  51. Function TimerTicks:Int( timer:TTimer )
  52. Return timer.Ticks()
  53. End Function
  54. Rem
  55. bbdoc: Wait until a timer ticks
  56. returns: The number of ticks since the last call to #WaitTimer
  57. End Rem
  58. Function WaitTimer:Int( timer:TTimer )
  59. Return timer.Wait()
  60. End Function
  61. Rem
  62. bbdoc: Stop a timer
  63. about:Once stopped, a timer can no longer be used.
  64. End Rem
  65. Function StopTimer( timer:TTimer )
  66. timer.Stop
  67. End Function
  68. Private
  69. Global timer_factories:TTimerFactory
  70. Public
  71. Type TTimerFactory
  72. Field _succ:TTimerFactory
  73. Method New()
  74. If _succ <> Null Then
  75. Throw "Timer already installed : " + _succ.GetName()
  76. End If
  77. _succ=timer_factories
  78. timer_factories=Self
  79. End Method
  80. Method GetName:String() Abstract
  81. Method Create:TTimer(hertz:Float,event:TEvent=Null) Abstract
  82. End Type
  83. Rem
  84. bbdoc: A high resolution timing mechanism.
  85. End Rem
  86. Type TChrono
  87. Const TICKS_PER_MILLIS:Int = 10000
  88. Const TICKS_PER_SEC:Int = TICKS_PER_MILLIS * 1000
  89. Const SECS_TO_NS:ULong = 1000000000:ULong
  90. Const FREQUENCY:Double = 1000000000.0
  91. Const tickFrequency:Double = TICKS_PER_SEC / FREQUENCY
  92. Field isRunning:Int
  93. Field startTimestamp:ULong
  94. Field elapsed:ULong
  95. Rem
  96. bbdoc: Creates a new #TChrono instance.
  97. End Rem
  98. Method New()
  99. Reset()
  100. End Method
  101. Method Reset()
  102. elapsed = 0
  103. isRunning = False
  104. startTimestamp = 0
  105. End Method
  106. Rem
  107. bbdoc: Restarts the timing mechanism.
  108. End Rem
  109. Method Restart()
  110. elapsed = 0
  111. startTimestamp = GetTimestamp()
  112. isRunning = True
  113. End Method
  114. Rem
  115. bbdoc: Returns the number of elapsed ticks since the timing mechanism was started.
  116. End Rem
  117. Method GetElapsedTicks:Long()
  118. Local timeElapsed:Long = elapsed
  119. If isRunning Then
  120. Local currentTimestamp:ULong = GetTimestamp()
  121. Local elapsedUntilNow:ULong = currentTimestamp - startTimestamp
  122. timeElapsed :+ elapsedUntilNow
  123. End If
  124. Return timeElapsed
  125. End Method
  126. Rem
  127. bbdoc: Returns the number of elapsed milliseconds since the timing mechanism was started.
  128. End Rem
  129. Method GetElapsedMilliseconds:ULong()
  130. Return GetElapsedDateTimeTicks() / TICKS_PER_MILLIS
  131. End Method
  132. Rem
  133. bbdoc:
  134. End Rem
  135. Method GetElapsedDateTimeTicks:ULong()
  136. Local ticks:Double = GetElapsedTicks()
  137. ticks :* tickFrequency
  138. Return ULong(ticks)
  139. End Method
  140. Rem
  141. bbdoc: Returns the current timestamp, in ns.
  142. End Rem
  143. Function GetTimestamp:ULong()
  144. ?Not macos
  145. Local tv:STimeSpec
  146. clock_gettime_(1, tv)
  147. Return tv.tv_sec * SECS_TO_NS + tv.tv_nsec
  148. ?macos
  149. Return mach_absolute_time_ns()
  150. ?
  151. End Function
  152. Rem
  153. bbdoc: Starts the timimg mechanism.
  154. End Rem
  155. Method Start()
  156. If Not isRunning Then
  157. startTimestamp = GetTimestamp()
  158. isRunning = True
  159. End If
  160. End Method
  161. Rem
  162. bbdoc: Stops the timing mechanism.
  163. End Rem
  164. Method Stop()
  165. If isRunning Then
  166. Local endTimestamp:ULong = GetTimestamp()
  167. Local elapsedThisPeriod:ULong = endTimestamp - startTimestamp
  168. elapsed :+ elapsedThisPeriod
  169. isRunning = False
  170. End If
  171. End Method
  172. Rem
  173. bbdoc: Creates, and optionally starts an instance of #TChrono.
  174. End Rem
  175. Function Create:TChrono(start:Int = True)
  176. Local stopWatch:TChrono = New TChrono
  177. If start Then
  178. stopWatch.Start()
  179. End If
  180. Return stopWatch
  181. End Function
  182. End Type