EntryPoint.hx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package haxe;
  2. #if target.threaded
  3. import sys.thread.Lock;
  4. import sys.thread.Mutex;
  5. import sys.thread.Thread;
  6. #elseif sys
  7. private class Lock {
  8. public function new() {}
  9. public inline function release() {}
  10. public inline function wait(?t:Float) {}
  11. }
  12. private class Mutex {
  13. public function new() {}
  14. public inline function acquire() {}
  15. public inline function release() {}
  16. }
  17. private class Thread {
  18. public static function create(f:Void->Void) {
  19. f();
  20. }
  21. }
  22. #end
  23. /**
  24. If `haxe.MainLoop` is kept from DCE, then we will insert an `haxe.EntryPoint.run()` call just at then end of `main()`.
  25. This class can be redefined by custom frameworks so they can handle their own main loop logic.
  26. **/
  27. class EntryPoint {
  28. #if sys
  29. static var sleepLock = new Lock();
  30. static var mutex = new Mutex();
  31. #end
  32. static var pending = new Array<Void->Void>();
  33. public static var threadCount(default, null):Int = 0;
  34. /**
  35. Wakeup a sleeping `run()`
  36. **/
  37. public static function wakeup() {
  38. #if sys
  39. sleepLock.release();
  40. #end
  41. }
  42. public static function runInMainThread(f:Void->Void) {
  43. #if sys
  44. mutex.acquire();
  45. pending.push(f);
  46. mutex.release();
  47. wakeup();
  48. #else
  49. pending.push(f);
  50. #end
  51. }
  52. public static function addThread(f:Void->Void) {
  53. #if sys
  54. mutex.acquire();
  55. threadCount++;
  56. mutex.release();
  57. Thread.create(function() {
  58. f();
  59. mutex.acquire();
  60. threadCount--;
  61. if (threadCount == 0)
  62. wakeup();
  63. mutex.release();
  64. });
  65. #else
  66. threadCount++;
  67. pending.push(function() {
  68. f();
  69. threadCount--;
  70. });
  71. #end
  72. }
  73. static function processEvents():Float {
  74. // flush all pending calls
  75. while (true) {
  76. #if sys
  77. mutex.acquire();
  78. var f = pending.shift();
  79. mutex.release();
  80. #else
  81. var f = pending.shift();
  82. #end
  83. if (f == null)
  84. break;
  85. f();
  86. }
  87. var time = @:privateAccess MainLoop.tick();
  88. if (!MainLoop.hasEvents() && threadCount == 0)
  89. return -1;
  90. return time;
  91. }
  92. /**
  93. Start the main loop. Depending on the platform, this can return immediately or will only return when the application exits.
  94. **/
  95. @:keep public static function run() @:privateAccess {
  96. #if js
  97. var nextTick = processEvents();
  98. inline function setTimeoutNextTick() {
  99. if (nextTick >= 0) {
  100. (untyped setTimeout)(run, nextTick * 1000);
  101. }
  102. }
  103. #if nodejs
  104. setTimeoutNextTick();
  105. #else
  106. if(js.Lib.typeof(js.Browser.window) != 'undefined') {
  107. var window:Dynamic = js.Browser.window;
  108. var rqf:Dynamic = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
  109. if(rqf != null) {
  110. rqf(run);
  111. } else {
  112. setTimeoutNextTick();
  113. }
  114. } else {
  115. setTimeoutNextTick();
  116. }
  117. #end
  118. #elseif flash
  119. flash.Lib.current.stage.addEventListener(flash.events.Event.ENTER_FRAME, function(_) processEvents());
  120. #elseif sys
  121. while (true) {
  122. var nextTick = processEvents();
  123. if (nextTick < 0)
  124. break;
  125. if (nextTick > 0)
  126. sleepLock.wait(nextTick); // wait until nextTick or wakeup() call
  127. }
  128. #else
  129. // no implementation available, let's exit immediately
  130. #end
  131. }
  132. }