Timer.hx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * Copyright (C)2005-2019 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. package haxe;
  23. /**
  24. The `Timer` class allows you to create asynchronous timers on platforms that
  25. support events.
  26. The intended usage is to create an instance of the `Timer` class with a given
  27. interval, set its `run()` method to a custom function to be invoked and
  28. eventually call `stop()` to stop the `Timer`.
  29. Note that a running `Timer` may or may not prevent the program to exit
  30. automatically when `main()` returns.
  31. It is also possible to extend this class and override its `run()` method in
  32. the child class.
  33. **/
  34. class Timer {
  35. #if (flash || js)
  36. private var id:Null<Int>;
  37. #elseif (java && !jvm)
  38. private var timer:java.util.Timer;
  39. private var task:java.util.TimerTask;
  40. #else
  41. private var event:MainLoop.MainEvent;
  42. #end
  43. /**
  44. Creates a new timer that will run every `time_ms` milliseconds.
  45. After creating the Timer instance, it calls `this.run` repeatedly,
  46. with delays of `time_ms` milliseconds, until `this.stop` is called.
  47. The first invocation occurs after `time_ms` milliseconds, not
  48. immediately.
  49. The accuracy of this may be platform-dependent.
  50. **/
  51. public function new(time_ms:Int) {
  52. #if flash
  53. var me = this;
  54. id = untyped __global__["flash.utils.setInterval"](function() {
  55. me.run();
  56. }, time_ms);
  57. #elseif js
  58. var me = this;
  59. id = untyped setInterval(function() me.run(), time_ms);
  60. #elseif (java && !jvm)
  61. timer = new java.util.Timer();
  62. timer.scheduleAtFixedRate(task = new TimerTask(this), haxe.Int64.ofInt(time_ms), haxe.Int64.ofInt(time_ms));
  63. #else
  64. var dt = time_ms / 1000;
  65. event = MainLoop.add(function() {
  66. @:privateAccess event.nextRun += dt;
  67. run();
  68. });
  69. event.delay(dt);
  70. #end
  71. }
  72. /**
  73. Stops `this` Timer.
  74. After calling this method, no additional invocations of `this.run`
  75. will occur.
  76. It is not possible to restart `this` Timer once stopped.
  77. **/
  78. public function stop() {
  79. #if (flash || js)
  80. if (id == null)
  81. return;
  82. #if flash
  83. untyped __global__["flash.utils.clearInterval"](id);
  84. #elseif js
  85. untyped clearInterval(id);
  86. #end
  87. id = null;
  88. #elseif (java && !jvm)
  89. if (timer != null) {
  90. timer.cancel();
  91. timer = null;
  92. }
  93. task = null;
  94. #else
  95. if (event != null) {
  96. event.stop();
  97. event = null;
  98. }
  99. #end
  100. }
  101. /**
  102. This method is invoked repeatedly on `this` Timer.
  103. It can be overridden in a subclass, or rebound directly to a custom
  104. function:
  105. ```haxe
  106. var timer = new haxe.Timer(1000); // 1000ms delay
  107. timer.run = function() { ... }
  108. ```
  109. Once bound, it can still be rebound to different functions until `this`
  110. Timer is stopped through a call to `this.stop`.
  111. **/
  112. public dynamic function run() {}
  113. /**
  114. Invokes `f` after `time_ms` milliseconds.
  115. This is a convenience function for creating a new Timer instance with
  116. `time_ms` as argument, binding its `run()` method to `f` and then stopping
  117. `this` Timer upon the first invocation.
  118. If `f` is `null`, the result is unspecified.
  119. **/
  120. public static function delay(f:Void->Void, time_ms:Int) {
  121. var t = new haxe.Timer(time_ms);
  122. t.run = function() {
  123. t.stop();
  124. f();
  125. };
  126. return t;
  127. }
  128. /**
  129. Measures the time it takes to execute `f`, in seconds with fractions.
  130. This is a convenience function for calculating the difference between
  131. `Timer.stamp()` before and after the invocation of `f`.
  132. The difference is passed as argument to `Log.trace()`, with `"s"` appended
  133. to denote the unit. The optional `pos` argument is passed through.
  134. If `f` is `null`, the result is unspecified.
  135. **/
  136. public static function measure<T>(f:Void->T, ?pos:PosInfos):T {
  137. var t0 = stamp();
  138. var r = f();
  139. Log.trace((stamp() - t0) + "s", pos);
  140. return r;
  141. }
  142. /**
  143. Returns a timestamp, in seconds with fractions.
  144. The value itself might differ depending on platforms, only differences
  145. between two values make sense.
  146. **/
  147. public static inline function stamp():Float {
  148. #if flash
  149. return flash.Lib.getTimer() / 1000;
  150. #elseif js
  151. #if nodejs
  152. var hrtime = js.Syntax.code('process.hrtime()'); // [seconds, remaining nanoseconds]
  153. return hrtime[0] + hrtime[1] / 1e9;
  154. #else
  155. return @:privateAccess HxOverrides.now() / 1000;
  156. #end
  157. #elseif cpp
  158. return untyped __global__.__time_stamp();
  159. #elseif python
  160. return Sys.cpuTime();
  161. #elseif sys
  162. return Sys.time();
  163. #else
  164. return 0;
  165. #end
  166. }
  167. }
  168. #if (java && !jvm)
  169. @:nativeGen
  170. private class TimerTask extends java.util.TimerTask {
  171. var timer:Timer;
  172. public function new(timer:Timer):Void {
  173. super();
  174. this.timer = timer;
  175. }
  176. @:overload override public function run():Void {
  177. timer.run();
  178. }
  179. }
  180. #end